perm filename CLOOPS.3[COM,LSP] blob
sn#847191 filedate 1987-10-17 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00468 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00070 00002
C00071 00003 ∂17-Apr-87 1011 @ALDERAAN.SCRC.Symbolics.COM:jlb@WAIKATO.S4CC.Symbolics.COM "Object" System
C00074 00004 ∂17-Apr-87 1149 Moon@ALDERAAN.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
C00085 00005 ∂17-Apr-87 1244 Moon@STONY-BROOK.SCRC.Symbolics.COM (long) CLOS Declaration Proposal Text
C00089 00006 ∂20-Apr-87 1331 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
C00098 00007 ∂20-Apr-87 1355 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
C00101 00008 ∂20-Apr-87 1449 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
C00103 00009 ∂21-Apr-87 0812 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
C00107 00010 ∂21-Apr-87 1049 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
C00111 00011 ∂22-Apr-87 1348 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00121 00012 ∂22-Apr-87 1448 Gregor.pa@Xerox.COM CL types --> classes
C00124 00013 ∂22-Apr-87 1533 Pavel.pa@Xerox.COM Re: CL types --> classes
C00126 00014 ∂22-Apr-87 1637 Gregor.pa@Xerox.COM note about clos instance disjointness
C00128 00015 ∂22-Apr-87 1639 Gregor.pa@Xerox.COM funcallable-standard-class
C00130 00016 ∂22-Apr-87 1729 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00138 00017 ∂23-Apr-87 0953 kempf%hplabsc@hplabs.HP.COM Re: CLOS Type Cleanup
C00140 00018 ∂23-Apr-87 1225 kempf%hplabsc@hplabs.HP.COM Re: (long) CLOS Declaration Proposal Text
C00147 00019 ∂23-Apr-87 1249 kempf%hplabsc@hplabs.HP.COM Re: Object Creation Discussion (at last!)
C00160 00020 ∂23-Apr-87 1456 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CLOS Declaration Proposal
C00162 00021 ∂23-Apr-87 1722 kempf%hplabsc@hplabs.HP.COM Re: CLOS Declaration Proposal
C00164 00022 ∂23-Apr-87 2020 Gregor.pa@Xerox.COM Re: Object Creation Discussion (at last!)
C00170 00023 ∂23-Apr-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM CL types --> classes
C00175 00024 ∂26-Apr-87 2231 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
C00200 00025 ∂27-Apr-87 1329 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
C00214 00026 ∂29-Apr-87 1836 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
C00216 00027 ∂06-May-87 0936 kempf%hplabsc@hplabs.HP.COM Printing Objects
C00218 00028 ∂06-May-87 1142 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Printing Objects
C00221 00029 ∂06-May-87 1304 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
C00224 00030 ∂06-May-87 2024 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Printing Objects
C00230 00031 ∂06-May-87 2202 Masinter.pa@Xerox.COM Re: Printing Objects
C00233 00032 ∂06-May-87 2235 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Printing Objects
C00238 00033 ∂07-May-87 0851 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
C00244 00034 ∂13-May-87 1131 kempf%hplabsc@hplabs.HP.COM Object Printing Discussion
C00254 00035 ∂13-May-87 1323 Gregor.pa@Xerox.COM Re: Object Printing Discussion
C00259 00036 ∂13-May-87 1444 DLW@ALDERAAN.SCRC.Symbolics.COM Object Printing Discussion
C00263 00037 ∂14-May-87 1322 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
C00268 00038 ∂15-May-87 1110 Gregor.pa@Xerox.COM optimization versus constructors
C00272 00039 ∂15-May-87 1240 kempf%hplabsc@hplabs.HP.COM Why is MAKE-INSTANCE not generic?
C00274 00040 ∂15-May-87 1315 kempf%hplabsc@hplabs.HP.COM Re: Why in MAKE-INSTANCE not generic?
C00276 00041 ∂15-May-87 1648 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Why in MAKE-INSTANCE not generic?
C00278 00042 ∂15-May-87 1715 Moon@STONY-BROOK.SCRC.Symbolics.COM optimization versus constructors
C00282 00043 ∂20-May-87 1934 Pavel.pa@Xerox.COM CLOS vs. subtypes of FLOAT
C00294 00044 ∂21-May-87 1228 Pavel.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
C00296 00045 ∂21-May-87 1227 Masinter.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
C00298 00046 ∂21-May-87 1338 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CLOS vs. subtypes of FLOAT
C00301 00047 ∂21-May-87 1909 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00318 00048 ∂22-May-87 0627 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: CLOS vs. subtypes of FLOAT
C00323 00049 ∂22-May-87 0725 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
C00327 00050 ∂22-May-87 1002 kempf%hplabsc@hplabs.HP.COM Arguments to CALL-NEXT-METHOD
C00329 00051 ∂22-May-87 1116 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00332 00052 ∂22-May-87 1635 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00339 00053 ∂23-May-87 0414 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00341 00054 ∂23-May-87 1622 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00344 00055 ∂23-May-87 1839 Bobrow.pa@Xerox.COM Object creation discussion (at last!)
C00361 00056 ∂25-May-87 0816 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00364 00057 ∂25-May-87 1754 masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00366 00058 ∂25-May-87 1818 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00368 00059 ∂26-May-87 1724 Masinter.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
C00371 00060 ∂26-May-87 2253 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
C00377 00061 ∂26-May-87 2259 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
C00386 00062 ∂26-May-87 2335 kempf%hplabsc@hplabs.HP.COM Re: CLOS vs. subtypes of FLOAT
C00388 00063 ∂27-May-87 0803 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00392 00064 ∂27-May-87 1057 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
C00394 00065 ∂27-May-87 1122 RPG OOPSLA Lisp and Object-Oriented Programming Workshop
C00396 00066 ∂27-May-87 1124 RPG Floats
C00410 00067 ∂27-May-87 1331 Masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00413 00068 ∂27-May-87 1604 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00415 00069 ∂27-May-87 1604 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00417 00070 ∂27-May-87 1605 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00421 00071 ∂27-May-87 1753 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
C00423 00072 ∂27-May-87 1909 kahn.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00425 00073 ∂27-May-87 1910 Gregor.pa@Xerox.COM OK, I stand corrected
C00429 00074 ∂27-May-87 1910 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00432 00075 ∂27-May-87 1910 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00434 00076 ∂28-May-87 0413 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00435 00077 ∂28-May-87 0804 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00437 00078 ∂28-May-87 0856 kempf%hplabsc@hplabs.HP.COM Re: Floats
C00443 00079 ∂28-May-87 1158 Masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00445 00080 ∂28-May-87 1251 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00447 00081 ∂28-May-87 1458 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00449 00082 ∂28-May-87 1511 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
C00451 00083 ∂28-May-87 1532 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
C00453 00084 ∂28-May-87 2159 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
C00456 00085 ∂29-May-87 1418 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
C00470 00086 ∂29-May-87 1430 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
C00487 00087 ∂29-May-87 1818 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
C00492 00088 ∂29-May-87 2300 RPG Object Creation (at last!)
C00494 00089 ∂31-May-87 1313 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00503 00090 ∂31-May-87 1439 masinter.pa@Xerox.COM Re: Object Creation (at last!)
C00505 00091 ∂31-May-87 1644 RPG Object creation discussion (at last!)
C00529 00092 ∂01-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00531 00093 ∂02-Jun-87 1029 RPG object / cleanup subcommittee interaction
C00533 00094 ∂02-Jun-87 1203 Bobrow.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00535 00095 ∂02-Jun-87 1642 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
C00537 00096 ∂02-Jun-87 2022 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
C00543 00097 ∂03-Jun-87 1220 Bobrow.pa@Xerox.COM Re: Floats
C00547 00098 ∂03-Jun-87 1221 Gregor.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00549 00099 ∂03-Jun-87 1455 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
C00551 00100 ∂03-Jun-87 1709 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00568 00101 ∂03-Jun-87 2020 RPG My Message of May 29
C00571 00102 ∂04-Jun-87 1004 kempf%hplabsc@hplabs.HP.COM SETF- method names
C00574 00103 ∂04-Jun-87 1525 kempf%hplabsc@hplabs.HP.COM Re: object creation / initialization discussion
C00579 00104 ∂05-Jun-87 2359 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00586 00105 ∂06-Jun-87 1219 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00593 00106 ∂06-Jun-87 1350 RPG Order of Initialization
C00600 00107 ∂06-Jun-87 1624 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00605 00108 ∂06-Jun-87 1636 RPG Order of Initialization
C00606 00109 ∂08-Jun-87 1907 Bobrow.pa@Xerox.COM Open Issues in 87-002
C00613 00110 ∂09-Jun-87 0719 skeene@STONY-BROOK.SCRC.Symbolics.COM Open Issues in 87-002
C00615 00111 ∂09-Jun-87 0803 kempf%hplabsc@hplabs.HP.COM I. Formal Specification of Gen. Fcn. Invocation
C00622 00112 ∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM II. Formal Specification of Gen. Fcn. Invocation
C00627 00113 ∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM III. Formal Specification of Gen. Fcn. Invocation
C00633 00114 ∂09-Jun-87 0805 kempf%hplabsc@hplabs.HP.COM IV. Formal Specification of Gen. Fcn. Invocation
C00642 00115 ∂09-Jun-87 0854 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00645 00116 ∂09-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
C00654 00117 ∂09-Jun-87 1008 kahn.pa@Xerox.COM Re: Open Issues in 87-002
C00656 00118 ∂09-Jun-87 1035 Bobrow.pa@Xerox.COM Re: Open Issues in 87-002
C00658 00119 ∂09-Jun-87 1050 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
C00660 00120 ∂09-Jun-87 1104 Bobrow.pa@Xerox.COM Re: Order of Initialization
C00664 00121 ∂09-Jun-87 1136 Bobrow.pa@Xerox.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00669 00122 ∂09-Jun-87 1743 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Object creation discussion (at last!)
C00675 00123 ∂09-Jun-87 1819 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
C00680 00124 ∂09-Jun-87 1832 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00683 00125 ∂09-Jun-87 1852 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
C00689 00126 ∂09-Jun-87 1921 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00695 00127 ∂09-Jun-87 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM I. Formal Specification of Gen. Fcn. Invocation
C00699 00128 ∂09-Jun-87 2234 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00702 00129 ∂09-Jun-87 2349 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00704 00130 ∂10-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00719 00131 ∂10-Jun-87 1006 RPG CLOS Document
C00720 00132 ∂10-Jun-87 1114 skeene@STONY-BROOK.SCRC.Symbolics.COM Concepts chapter on standard type classes
C00728 00133 ∂10-Jun-87 1117 skeene@STONY-BROOK.SCRC.Symbolics.COM Design Rationale section on standard type classes
C00739 00134 ∂10-Jun-87 1412 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00741 00135 ∂10-Jun-87 1627 Bobrow.pa@Xerox.COM Re: SETF- method names
C00744 00136 ∂10-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation Discussion
C00746 00137 ∂10-Jun-87 2338 RPG
C00750 00138 ∂11-Jun-87 0746 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00752 00139 ∂11-Jun-87 0819 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00757 00140 ∂11-Jun-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: SETF- method names
C00762 00141 ∂11-Jun-87 1243 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00766 00142 ∂12-Jun-87 1002 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Metaclass Protocol
C00773 00143 ∂12-Jun-87 1204 Bobrow.pa@Xerox.COM Re: Order of Initialization
C00775 00144 ∂15-Jun-87 1118 Gregor.pa@Xerox.COM new new initialization protocol blues
C00783 00145 ∂15-Jun-87 1920 Bobrow.pa@Xerox.COM Re: new new initialization protocol blues
C00788 00146 ∂23-Jun-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation
C00802 00147 ∂24-Jun-87 1045 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation
C00807 00148 ∂24-Jun-87 1155 RPG Request to Moon for Thursday's Discussion
C00808 00149 ∂25-Jun-87 0901 RPG Random Thoughts Concerning Initialization
C00812 00150 ∂02-Jul-87 0911 kempf%hplabsc@hplabs.HP.COM ECOOP Reaction to CLOS
C00816 00151 ∂03-Jul-87 0843 Moon@STONY-BROOK.SCRC.Symbolics.COM ECOOP Reaction to CLOS
C00818 00152 ∂06-Jul-87 1130 RPG ECOOP Reaction
C00823 00153 ∂08-Jul-87 0928 RPG First Try at Terminology
C00837 00154 ∂08-Jul-87 0938 RPG Category Errors
C00840 00155 ∂08-Jul-87 1643 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
C00844 00156 ∂09-Jul-87 1207 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00847 00157 ∂09-Jul-87 1326 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C00854 00158 ∂09-Jul-87 1327 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
C00858 00159 ∂09-Jul-87 1329 kempf%hplabsz@hplabs.HP.COM Re: First Try at Terminology
C00862 00160 ∂09-Jul-87 1333 kempf%hplabsz@hplabs.HP.COM Re: Metaclass Protocol Goals
C00870 00161 ∂09-Jul-87 1355 Kahn.pa@Xerox.COM Re: Category Errors
C00872 00162 ∂09-Jul-87 1431 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
C00875 00163 ∂09-Jul-87 1933 Bobrow.pa@Xerox.COM Re: Metaclass Protocol Goals
C00877 00164 ∂10-Jul-87 1026 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00882 00165 ∂13-Jul-87 1039 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Metaclass Protocol Goals
C00892 00166 ∂15-Jul-87 1000 kempf%hplabsz@hplabs.HP.COM Re: Class redefinition and class-changed.
C00895 00167 ∂16-Jul-87 0752 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00898 00168 ∂22-Jul-87 0639 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
C00905 00169 ∂22-Jul-87 1014 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
C00909 00170 ∂23-Jul-87 1812 Gregor.pa@Xerox.COM initialization meeting notes
C00916 00171 ∂23-Jul-87 1917 Bobrow.pa@Xerox.COM Re: Category Errors
C00918 00172 ∂23-Jul-87 1941 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00921 00173 ∂24-Jul-87 0623 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00924 00174 ∂24-Jul-87 0854 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00927 00175 ∂24-Jul-87 1133 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Category Errors
C00931 00176 ∂24-Jul-87 1136 RPG Category Errors
C00935 00177 ∂24-Jul-87 1420 Bobrow.pa@Xerox.COM Re: Category Errors
C00939 00178 ∂24-Jul-87 1421 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00942 00179 ∂24-Jul-87 1427 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
C00945 00180 ∂24-Jul-87 1436 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
C00948 00181 ∂24-Jul-87 1437 Moon@STONY-BROOK.SCRC.Symbolics.COM First Try at Terminology
C00951 00182 ∂24-Jul-87 1459 RPG Category Errors
C00953 00183 ∂24-Jul-87 1645 RPG Class Redefinition
C00957 00184 ∂25-Jul-87 0719 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
C00960 00185 ∂25-Jul-87 0720 Moon@STONY-BROOK.SCRC.Symbolics.COM Class redefinition and class-changed.
C00984 00186 ∂27-Jul-87 0930 kempf%hplabsz@hplabs.HP.COM Re: Class Redefinition
C00986 00187 ∂27-Jul-87 0933 kempf%hplabsz@hplabs.HP.COM Technical corrections in 87-002
C00993 00188 ∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Name That Class
C00995 00189 ∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Redefinition
C00999 00190 ∂27-Jul-87 1046 Bobrow.pa@Xerox.COM Re: Name That Class
C01001 00191 ∂27-Jul-87 1159 RPG Name That Class
C01002 00192 ∂27-Jul-87 1224 RPG Class Redefinition
C01003 00193 ∂27-Jul-87 1700 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class Redefinition
C01011 00194 ∂27-Jul-87 1905 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
C01017 00195 ∂27-Jul-87 2012 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01042 00196 ∂28-Jul-87 1447 Bobrow.pa@Xerox.COM Re: Category Errors
C01045 00197 ∂28-Jul-87 1527 Bobrow.pa@Xerox.COM Re: Class Redefinition
C01049 00198 ∂28-Jul-87 1550 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C01054 00199 ∂28-Jul-87 1642 Gregor.pa@Xerox.COM Re: Class Redefinition
C01056 00200 ∂28-Jul-87 1648 Gregor.pa@Xerox.COM Re: Class Redefinition
C01058 00201 ∂28-Jul-87 1751 Bobrow.pa@Xerox.COM Re: initialization meeting notes
C01060 00202 ∂28-Jul-87 1907 Gregor.pa@Xerox.COM Re: initialization meeting notes
C01065 00203 ∂28-Jul-87 1922 Gregor.pa@Xerox.COM Re: Name That Class
C01069 00204 ∂28-Jul-87 2126 RPG Partial Orderings
C01070 00205 ∂29-Jul-87 1025 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Miscellaneous decisions taken or to be taken
C01073 00206 ∂29-Jul-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM updated documentation
C01076 00207 ∂29-Jul-87 1415 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
C01086 00208 ∂30-Jul-87 0021 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
C01114 00209 ∂30-Jul-87 0612 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Miscellaneous decisions taken or to be taken
C01124 00210 ∂30-Jul-87 1306 Bobrow.pa@Xerox.COM Re: Name That Class
C01126 00211 ∂31-Jul-87 0939 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
C01132 00212 ∂31-Jul-87 1110 kempf%hplabsz@hplabs.HP.COM TRACE Proposal (Version 1)
C01143 00213 ∂02-Aug-87 1725 RPG Miscellenia
C01146 00214 ∂03-Aug-87 1656 kempf%hplabsz@hplabs.HP.COM Re: Miscellenia
C01150 00215 ∂04-Aug-87 2243 kempf%hplabsz@hplabs.HP.COM Re: Technical corrections in 87-002
C01156 00216 ∂05-Aug-87 1751 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
C01162 00217 ∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellenia
C01165 00218 ∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM TRACE Proposal (Version 1)
C01171 00219 ∂06-Aug-87 1914 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Name That Class
C01177 00220 ∂06-Aug-87 1929 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01210 00221 ∂09-Aug-87 1514 Gregor.pa@Xerox.COM Miscellaneous decisions taken or to be taken
C01234 00222 ∂10-Aug-87 1122 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
C01241 00223 ∂10-Aug-87 1145 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Name That Class
C01244 00224 ∂10-Aug-87 1419 kempf%hplabsz@hplabs.HP.COM Re: TRACE Proposal (Version 1)
C01252 00225 ∂11-Aug-87 1504 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
C01266 00226 ∂13-Aug-87 0928 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Name That Class
C01271 00227 ∂17-Aug-87 2133 kempf%hplabsz@hplabs.HP.COM Environments, Naming, and CLOS (was Re: Name that Class)
C01281 00228 ∂18-Aug-87 0820 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Names to Objects and Compiler-environment
C01289 00229 ∂18-Aug-87 1136 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C01300 00230 ∂18-Aug-87 1146 Moon@STONY-BROOK.SCRC.Symbolics.COM Agenda for September meeting
C01306 00231 ∂18-Aug-87 1522 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C01310 00232 ∂18-Aug-87 1534 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
C01314 00233 ∂18-Aug-87 1615 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C01317 00234 ∂18-Aug-87 1707 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ECOOP Reaction to CLOS
C01325 00235 ∂18-Aug-87 1728 Moon@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
C01332 00236 ∂19-Aug-87 0632 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C01335 00237 ∂19-Aug-87 0745 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C01337 00238 ∂19-Aug-87 1020 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C01341 00239 ∂19-Aug-87 1123 skeene@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
C01343 00240 ∂19-Aug-87 1349 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C01347 00241 ∂19-Aug-87 1455 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Names to Objects and Compiler-environment
C01359 00242 ∂19-Aug-87 1737 Gregor.pa@Xerox.COM meeting place
C01361 00243 ∂19-Aug-87 1830 Moon@STONY-BROOK.SCRC.Symbolics.COM meeting place
C01363 00244 ∂20-Aug-87 0928 Moon@STONY-BROOK.SCRC.Symbolics.COM proposed syntactic cleanups in defmethod
C01376 00245 ∂20-Aug-87 1010 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01416 00246 ∂20-Aug-87 1525 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
C01421 00247 ∂21-Aug-87 0828 kempf%hplabsz@hplabs.HP.COM Re: proposed syntactic cleanups in defmethod
C01431 00248 ∂22-Aug-87 0004 Masinter.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C01433 00249 ∂22-Aug-87 0033 Masinter.pa@Xerox.COM Re: TRACE Proposal (Version 1)
C01435 00250 ∂22-Aug-87 1837 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
C01438 00251 ∂24-Aug-87 1146 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C01447 00252 ∂24-Aug-87 1254 LGD updated spec on SAIL
C01448 00253 ∂24-Aug-87 1304 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C01454 00254 ∂24-Aug-87 1644 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: proposed syntactic cleanups in defmethod
C01458 00255 ∂24-Aug-87 1701 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: short form of define-method-combination
C01463 00256 ∂26-Aug-87 1916 Gregor.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C01467 00257 ∂26-Aug-87 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
C01470 00258 ∂27-Aug-87 0952 kempf%hplabsz@hplabs.HP.COM Solutions to Name/Object Mapping for Generic Functions
C01478 00259 ∂27-Aug-87 1656 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Solutions to Name/Object Mapping for Generic Functions
C01482 00260 ∂27-Aug-87 1908 kempf%hplabsz@hplabs.HP.COM Re: Names to Objects and Compiler-environment
C01509 00261 ∂28-Aug-87 0150 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
C01512 00262 ∂28-Aug-87 1912 Moon@STONY-BROOK.SCRC.Symbolics.COM Another try on object creation
C01534 00263 ∂30-Aug-87 1946 RPG Class Precedence List
C01539 00264 ∂30-Aug-87 2009 RPG Miscellaneous decisions taken or to be taken
C01541 00265 ∂30-Aug-87 2017 RPG Agenda
C01543 00266 ∂30-Aug-87 2024 RPG Name That Class!
C01550 00267 ∂30-Aug-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
C01552 00268 ∂31-Aug-87 0802 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
C01556 00269 ∂31-Aug-87 1914 MLY@AI.AI.MIT.EDU RPG's recent typo.
C01557 00270 ∂01-Sep-87 1150 Gregor.pa@Xerox.COM Re: Name That Class!
C01560 00271 ∂01-Sep-87 1258 RPG Name That Class!
C01563 00272 ∂01-Sep-87 1300 RPG Anonymous Generic Function Proposal (Draft 1)
C01567 00273 ∂01-Sep-87 1823 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 1)
C01569 00274 ∂01-Sep-87 2317 RPG Anonymous Generic Function Proposal (Draft 2)
C01574 00275 ∂02-Sep-87 1149 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01576 00276 ∂02-Sep-87 1224 Pavel.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01578 00277 ∂02-Sep-87 1534 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Another try on object creation
C01581 00278 ∂02-Sep-87 2013 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
C01587 00279 ∂03-Sep-87 1414 Bobrow.pa@Xerox.COM Re: Another try on object creation
C01592 00280 ∂03-Sep-87 1705 kempf%hplabsz@hplabs.HP.COM Re: Solutions to Name/Object Mapping for Generic Functions
C01603 00281 ∂03-Sep-87 1838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
C01605 00282 ∂04-Sep-87 1058 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01609 00283 ∂04-Sep-87 1112 Lanning.pa@Xerox.COM WITH-SLOTS, "virtual" slots, and the meta-object protocol
C01612 00284 ∂08-Sep-87 1221 RPG WITH-ADDED-METHODS
C01614 00285 ∂09-Sep-87 1124 Bobrow.pa@Xerox.COM Updating Obsolete Instances
C01621 00286 ∂09-Sep-87 1630 Bobrow.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C01626 00287 ∂09-Sep-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM User control of the CPL
C01640 00288 ∂10-Sep-87 1101 kempf%hplabsz@hplabs.HP.COM Meeting on Sept. 17-18
C01642 00289 ∂10-Sep-87 1250 Bobrow.pa@Xerox.COM Re: Meeting on Sept. 17-18
C01644 00290 ∂10-Sep-87 2248 kempf%hplabsz@hplabs.HP.COM Trace Proposal (Version 2)
C01658 00291 ∂11-Sep-87 0827 skeene@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01662 00292 ∂11-Sep-87 1023 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01666 00293 ∂11-Sep-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C01670 00294 ∂11-Sep-87 1154 Bobrow.pa@Xerox.COM [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
C01681 00295 ∂11-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
C01692 00296 ∂11-Sep-87 1204 skeene@STONY-BROOK.SCRC.Symbolics.COM proposal for arguments for call-next-method
C01696 00297 ∂11-Sep-87 1314 Bobrow.pa@Xerox.COM Deoptimizing Slot Access
C01701 00298 ∂11-Sep-87 1335 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01704 00299 ∂11-Sep-87 1447 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: User control of the CPL
C01706 00300 ∂11-Sep-87 1641 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Updating Obsolete Instances
C01710 00301 ∂11-Sep-87 1657 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01713 00302 ∂11-Sep-87 2030 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01716 00303 ∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
C01721 00304 ∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01724 00305 ∂11-Sep-87 2058 Bobrow.pa@Xerox.COM Re: short form of define-method-combination
C01729 00306 ∂14-Sep-87 1346 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01732 00307 ∂14-Sep-87 1439 Bobrow.pa@Xerox.COM Uninitialized Slots
C01734 00308 ∂14-Sep-87 1446 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Miscellaneous decisions taken or to be taken
C01737 00309 ∂14-Sep-87 1510 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01740 00310 ∂14-Sep-87 1511 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized Slots
C01743 00311 ∂14-Sep-87 1532 kempf%hplabsz@hplabs.HP.COM Re: User control of the CPL
C01753 00312 ∂14-Sep-87 1547 Masinter.pa@Xerox.COM Re: Uninitialized Slots
C01755 00313 ∂14-Sep-87 1642 Bobrow.pa@Xerox.COM Re: Agenda for September meeting
C01758 00314 ∂14-Sep-87 2058 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
C01763 00315 ∂14-Sep-87 2129 Bobrow.pa@Xerox.COM Re: Names to Objects and Compiler-environment
C01767 00316 ∂15-Sep-87 0923 RPG Uninitialized Slots
C01769 00317 ∂15-Sep-87 0935 RPG Proposals
C01770 00318 ∂15-Sep-87 1009 kempf%hplabsz@hplabs.HP.COM Re: Proposals
C01772 00319 ∂15-Sep-87 1356 Bobrow.pa@Xerox.COM Re: Uninitialized Slots
C01775 00320 ∂15-Sep-87 1627 kempf%hplabsz@hplabs.HP.COM Re: Updating Obsolete Instances (and CHANGE-CLASS)
C01780 00321 ∂15-Sep-87 1916 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Another try on object creation
C01784 00322 ∂15-Sep-87 2006 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01788 00323 ∂20-Sep-87 1904 Gregor.pa@Xerox.COM fixing our problems with setf
C01791 00324 ∂21-Sep-87 0911 Bobrow.pa@Xerox.COM Re: fixing our problems with setf
C01794 00325 ∂21-Sep-87 1109 RPG Issues on Dynamic Extent for CALL-NEXT-METHOD
C01804 00326 ∂21-Sep-87 1121 RPG New Trivial Issue: Implicit Blocks in Methods
C01807 00327 ∂21-Sep-87 1159 Moon@STONY-BROOK.SCRC.Symbolics.COM New Trivial Issue: Implicit Blocks in Methods
C01812 00328 ∂21-Sep-87 1231 Bobrow.pa@Xerox.COM Re: New Trivial Issue: Implicit Blocks in Methods
C01815 00329 ∂21-Sep-87 1232 Bobrow.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
C01817 00330 ∂21-Sep-87 1246 Masinter.pa@Xerox.COM Re: fixing our problems with setf
C01819 00331 ∂21-Sep-87 1312 Gregor.pa@Xerox.COM Re: fixing our problems with setf
C01821 00332 ∂21-Sep-87 1334 Moon@STONY-BROOK.SCRC.Symbolics.COM fixing our problems with setf
C01826 00333 ∂21-Sep-87 1555 Gregor.pa@Xerox.COM Re: New Trivial Issue: Implicit Blocks in Methods
C01828 00334 ∂21-Sep-87 1611 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: New Trivial Issue: Implicit Blocks in Methods
C01832 00335 ∂21-Sep-87 1615 Masinter.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
C01835 00336 ∂21-Sep-87 2135 RPG Issues on Dynamic Extent for CALL-NEXT-METHOD
C01836 00337 ∂22-Sep-87 1417 Moon@MEAD.SCRC.Symbolics.COM SLOT-BOUNDP or SLOT-BOUND-P
C01838 00338 ∂22-Sep-87 1802 Bobrow.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
C01840 00339 ∂22-Sep-87 2004 Moon@STONY-BROOK.SCRC.Symbolics.COM September version of object-creation
C01864 00340 ∂22-Sep-87 2008 Moon@STONY-BROOK.SCRC.Symbolics.COM Status of CLOS decisions
C01924 00341 ∂23-Sep-87 0427 skeene@STONY-BROOK.SCRC.Symbolics.COM draft of built-in method combination types
C01931 00342 ∂23-Sep-87 0851 Bobrow.pa@Xerox.COM Terminology: Shared versus class local versus instance
C01935 00343 ∂23-Sep-87 0907 Bobrow.pa@Xerox.COM Re: September version of object-creation
C01939 00344 ∂23-Sep-87 1022 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: September version of object-creation
C01941 00345 ∂23-Sep-87 1240 skeene@Riverside.SCRC.Symbolics.COM the new DEFMETHOD syntax
C01946 00346 ∂23-Sep-87 1330 Bobrow.pa@Xerox.COM Re: the new DEFMETHOD syntax
C01947 00347 ∂23-Sep-87 2202 RPG September version of object-creation (More nits)
C01948 00348 ∂23-Sep-87 2218 RPG Returning From a Generic Function
C01949 00349 ∂24-Sep-87 0856 Bobrow.pa@Xerox.COM no-applicable-method
C01954 00350 ∂24-Sep-87 0907 Bobrow.pa@Xerox.COM next-methods
C01956 00351 ∂24-Sep-87 0915 Bobrow.pa@Xerox.COM Redefining Classes
C01963 00352 ∂24-Sep-87 0919 Bobrow.pa@Xerox.COM DRAFT: Changing Names of Built-in classes
C01965 00353 ∂24-Sep-87 0919 Bobrow.pa@Xerox.COM Unbound Slots
C01968 00354 ∂24-Sep-87 0927 Bobrow.pa@Xerox.COM slot-missing
C01972 00355 ∂24-Sep-87 0937 Moon@STONY-BROOK.SCRC.Symbolics.COM September version of object-creation (More nits)
C01977 00356 ∂24-Sep-87 0942 Moon@MEAD.SCRC.Symbolics.COM Terminology: Shared versus class local versus instance
C01980 00357 ∂24-Sep-87 0951 Bobrow.pa@Xerox.COM Re: September version of object-creation (More nits)
C01982 00358 ∂24-Sep-87 0957 Moon@STONY-BROOK.SCRC.Symbolics.COM slot-missing
C01985 00359 ∂24-Sep-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: September version of object-creation (More nits)
C01987 00360 ∂24-Sep-87 1021 Bobrow.pa@Xerox.COM Re: Terminology: Shared versus class local versus instance
C01990 00361 ∂24-Sep-87 1051 Masinter.pa@Xerox.COM Re: next-methods
C01992 00362 ∂24-Sep-87 1124 RPG NEXT-METHODS
C01993 00363 ∂24-Sep-87 1142 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: next-methods
C01996 00364 ∂24-Sep-87 1458 Gregor.pa@Xerox.COM Re: next-methods
C01998 00365 ∂24-Sep-87 1549 Masinter.pa@Xerox.COM Re: next-methods
C02000 00366 ∂24-Sep-87 2035 Moon@STONY-BROOK.SCRC.Symbolics.COM Redefining Classes
C02013 00367 ∂25-Sep-87 1208 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Exact type
C02016 00368 ∂25-Sep-87 1258 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: fixing our problems with setf
C02020 00369 ∂25-Sep-87 1841 Moon@STONY-BROOK.SCRC.Symbolics.COM Amendments requiring additional writing
C02027 00370 ∂26-Sep-87 1639 Masinter.pa@Xerox.COM Re: Amendments requiring additional writing
C02030 00371 ∂28-Sep-87 0623 muehle%orion@cs.utah.edu remove me from the list
C02031 00372 ∂28-Sep-87 0842 kempf%hplabsz@hplabs.HP.COM Various Topics Discussed Last Week
C02044 00373 ∂28-Sep-87 0922 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Amendments requiring additional writing
C02051 00374 ∂28-Sep-87 1006 Moon@STONY-BROOK.SCRC.Symbolics.COM Various Topics Discussed Last Week
C02060 00375 ∂28-Sep-87 1026 Bobrow.pa@Xerox.COM key argument versus keyword argument
C02062 00376 ∂28-Sep-87 1048 Moon@STONY-BROOK.SCRC.Symbolics.COM lambda-list congruence
C02066 00377 ∂28-Sep-87 1107 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: draft of built-in method combination types
C02069 00378 ∂28-Sep-87 1117 RPG Shared/localclass/instance
C02071 00379 ∂28-Sep-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM key argument versus keyword argument
C02074 00380 ∂28-Sep-87 1114 Moon@STONY-BROOK.SCRC.Symbolics.COM Revised draft of object creation proposal
C02101 00381 ∂28-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Shared/localclass/instance
C02105 00382 ∂28-Sep-87 1254 kempf%hplabsz@hplabs.HP.COM Re: Exact type
C02110 00383 ∂28-Sep-87 1336 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
C02116 00384 ∂28-Sep-87 1355 Moon@STONY-BROOK.SCRC.Symbolics.COM fixing our problems with setf
C02129 00385 ∂28-Sep-87 1407 Moon@STONY-BROOK.SCRC.Symbolics.COM Various Topics Discussed Last Week
C02133 00386 ∂28-Sep-87 1419 Bobrow.pa@Xerox.COM Re: fixing our problems with setf
C02135 00387 ∂28-Sep-87 1451 Bobrow.pa@Xerox.COM Re: Redefining Classes
C02148 00388 ∂28-Sep-87 1546 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Amendments requiring additional writing
C02159 00389 ∂28-Sep-87 1549 kempf%hplabsz@hplabs.HP.COM Re: draft of built-in method combination types
C02162 00390 ∂28-Sep-87 1556 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: fixing our problems with setf
C02165 00391 ∂28-Sep-87 1612 kempf%hplabsz@hplabs.HP.COM Re: Various Topics Discussed Last Week
C02170 00392 ∂28-Sep-87 1648 Bobrow.pa@Xerox.COM Re: Various Topics Discussed Last Week
C02174 00393 ∂28-Sep-87 1651 Bobrow.pa@Xerox.COM Re: Various Topics Discussed Last Week
C02178 00394 ∂28-Sep-87 1734 kempf%hplabsz@hplabs.HP.COM Re: fixing our problems with setf
C02180 00395 ∂28-Sep-87 1800 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Topics Discussed Last Week
C02184 00396 ∂28-Sep-87 1804 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: fixing our problems with setf
C02186 00397 ∂28-Sep-87 1836 RPG Shared/localclass/instance
C02189 00398 ∂28-Sep-87 1918 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Redefining Classes
C02207 00399 ∂29-Sep-87 0859 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
C02213 00400 ∂29-Sep-87 0928 RPG Various Decisions
C02214 00401 ∂29-Sep-87 0945 Gregor.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
C02217 00402 ∂29-Sep-87 1124 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
C02219 00403 ∂29-Sep-87 1150 Bobrow.pa@Xerox.COM Re: Shared/localclass/instance
C02221 00404 ∂29-Sep-87 1150 Bobrow.pa@Xerox.COM Re: Various Decisions
C02223 00405 ∂29-Sep-87 1222 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Decisions
C02227 00406 ∂29-Sep-87 1300 kempf%hplabsz@hplabs.HP.COM Re: Shared/localclass/instance
C02230 00407 ∂29-Sep-87 1415 Pavel.pa@Xerox.COM Re: Various Decisions
C02231 00408 ∂29-Sep-87 1440 kempf%hplabsz@hplabs.HP.COM Re: Status of CLOS decisions
C02233 00409 ∂29-Sep-87 1444 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Decisions
C02236 00410 ∂29-Sep-87 1514 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
C02239 00411 ∂29-Sep-87 1529 RPG Various Decisions
C02241 00412 ∂29-Sep-87 1625 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Redefining Classes
C02255 00413 ∂29-Sep-87 1732 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Various Topics Discussed Last Week
C02260 00414 ∂29-Sep-87 1733 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Redefining Classes
C02274 00415 ∂29-Sep-87 1733 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Exact type
C02278 00416 ∂29-Sep-87 1820 Bobrow.pa@Xerox.COM Re: Redefining Classes
C02282 00417 ∂29-Sep-87 1931 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Exact type
C02286 00418 ∂29-Sep-87 1935 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Various Topics Discussed Last Week
C02291 00419 ∂29-Sep-87 1939 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Revised draft of object creation proposal
C02294 00420 ∂29-Sep-87 1944 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Redefining Classes
C02298 00421 ∂30-Sep-87 0936 Moon@STONY-BROOK.SCRC.Symbolics.COM Constructors
C02320 00422 ∂30-Sep-87 1316 kempf%hplabsz@hplabs.HP.COM Re: Exact type
C02324 00423 ∂30-Sep-87 1326 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
C02327 00424 ∂30-Sep-87 1410 Moon@STONY-BROOK.SCRC.Symbolics.COM Should redefining a class reinitialize shared slots?
C02335 00425 ∂30-Sep-87 1353 Moon@STONY-BROOK.SCRC.Symbolics.COM Slot Inheritance
C02338 00426 ∂30-Sep-87 1403 RPG NEXT METHOD
C02341 00427 ∂30-Sep-87 1419 Moon@STONY-BROOK.SCRC.Symbolics.COM NEXT METHOD
C02343 00428 ∂30-Sep-87 1521 RPG Should redefining a class reinitialize shared slots?
C02345 00429 ∂30-Sep-87 1619 Bobrow.pa@Xerox.COM class/instance vs shared/local
C02347 00430 ∂30-Sep-87 1619 Bobrow.pa@Xerox.COM Re: next-method-p
C02348 00431 ∂30-Sep-87 1719 Moon@STONY-BROOK.SCRC.Symbolics.COM Should redefining a class reinitialize shared slots?
C02351 00432 ∂30-Sep-87 1748 kempf%hplabsz@hplabs.HP.COM Re: Should redefining a class reinitialize shared slots?
C02354 00433 ∂30-Sep-87 1756 Bobrow.pa@Xerox.COM Re: Should redefining a class reinitialize shared slots?
C02360 00434 ∂30-Sep-87 2045 Moon@STONY-BROOK.SCRC.Symbolics.COM Amendments requiring additional writing
C02371 00435 ∂30-Sep-87 2352 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/localclass/instance
C02373 00436 ∂01-Oct-87 0822 Bobrow.pa@Xerox.COM Re: Shared/localclass/instance
C02375 00437 ∂01-Oct-87 0834 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
C02379 00438 ∂01-Oct-87 0836 kempf%hplabsz@hplabs.HP.COM Re: Amendments requiring additional writing
C02381 00439 ∂01-Oct-87 0838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Should redefining a class reinitialize shared slots?
C02389 00440 ∂01-Oct-87 0901 kempf%hplabsz@hplabs.HP.COM CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
C02392 00441 ∂01-Oct-87 0911 Moon@ALLEGHENY.SCRC.Symbolics.COM Re: Amendments requiring additional writing
C02396 00442 ∂01-Oct-87 0925 kempf%hplabsz@hplabs.HP.COM COERCE (not urgent)
C02402 00443 ∂01-Oct-87 0950 Bobrow.pa@Xerox.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
C02405 00444 ∂01-Oct-87 0957 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
C02408 00445 ∂01-Oct-87 1017 kempf%hplabsz@hplabs.HP.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
C02411 00446 ∂01-Oct-87 1117 Bobrow.pa@Xerox.COM Can defgeneric provide defaults for &key args
C02413 00447 ∂01-Oct-87 1117 Bobrow.pa@Xerox.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
C02416 00448 ∂01-Oct-87 1244 kempf%hplabsz@hplabs.HP.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
C02419 00449 ∂01-Oct-87 1621 RPG Shared/classinstance/local
C02422 00450 ∂01-Oct-87 2100 Bobrow.pa@Xerox.COM Re: Shared/classinstance/local
C02426 00451 ∂02-Oct-87 0942 kempf%hplabsz@hplabs.HP.COM Re: Constructors
C02434 00452 ∂02-Oct-87 1017 kempf%hplabsz@hplabs.HP.COM Re: Can defgeneric provide defaults for &key args
C02436 00453 ∂02-Oct-87 1032 Moon@STONY-BROOK.SCRC.Symbolics.COM Can defgeneric provide defaults for &key args
C02438 00454 ∂02-Oct-87 1054 Gregor.pa@Xerox.COM no-applicable-method
C02441 00455 ∂02-Oct-87 1102 Moon@STONY-BROOK.SCRC.Symbolics.COM no-applicable-method
C02443 00456 ∂02-Oct-87 1132 Bobrow.pa@Xerox.COM Re: Constructors
C02450 00457 ∂02-Oct-87 1154 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Constructors
C02454 00458 ∂02-Oct-87 1256 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Constructors
C02465 00459 ∂02-Oct-87 1342 Bobrow.pa@Xerox.COM Re: Can defgeneric provide defaults for &key args
C02468 00460 ∂02-Oct-87 1400 Bobrow.pa@Xerox.COM Re: no-applicable-method
C02471 00461 ∂02-Oct-87 1404 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Can defgeneric provide defaults for &key args
C02473 00462 ∂02-Oct-87 1404 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Exact type
C02477 00463 ∂02-Oct-87 1417 Gregor.pa@Xerox.COM no-applicable-method
C02479 00464 ∂02-Oct-87 1640 Gregor.pa@Xerox.COM fixing our problems with setf
C02490 00465 ∂03-Oct-87 1149 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/localclass/instance
C02492 00466 ∂03-Oct-87 1300 Gregor.pa@Xerox.COM Constructors
C02510 00467 ∂03-Oct-87 1341 Gregor.pa@Xerox.COM Re: Constructors
C02514 00468 ∂03-Oct-87 1451 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/localclass/instance
C02516 ENDMK
C⊗;
∂17-Apr-87 1011 @ALDERAAN.SCRC.Symbolics.COM:jlb@WAIKATO.S4CC.Symbolics.COM "Object" System
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 17 Apr 87 10:00:37 PDT
Received: from FLYING-DOVE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 72959; Fri 17-Apr-87 13:00:56 EDT
Date: Fri, 17 Apr 87 13:01 EDT
From: Jonathan L. Balgley <jlb@WAIKATO.S4CC.Symbolics.COM>
Subject: "Object" System
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870417130124.4.JLB@FLYING-DOVE.SCRC.Symbolics.COM>
Hi! I've read the draft version of CLOS standard and gave my comments
through Symbolics' other representatives. But I have one question: Why
is it called the "Common Lisp Object System"?
I understand the desire to be related to the term "object-oriented", but
pure Common Lisp could already be called an "object system". Indeed,
CLtL dedicates an entire chapter (number 2, "Data Types") to discussing
the "variety of types of data objects". I believe that the name will
cause unnecessary confusion when trying to describe the facilities that
CLOS provides over pure Common Lisp. I can hear CL beginners now: "OK,
you've convinced me that conses and symbols are objects. How does that
relate to the Common Lisp Object System?"
So, have other names been proposed and turned down? Is this name
finalized or will you take other suggestions? If you will, here's my
idea for a name: "CL Generic Structure System". Another one, that Sonya
Keene proposed, was "Classes".
At the very least, I hope that the "Design Rationale" chapter will
briefly mention why it's named what it is. Thanks for listening.
∂17-Apr-87 1149 Moon@ALDERAAN.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 17 Apr 87 11:49:33 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 73015; Fri 17-Apr-87 14:49:44 EDT
Date: Fri, 17 Apr 87 14:49 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Object creation discussion (at last!)
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2754594256-919057@Jenner>
Message-ID: <870417144911.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 16 Apr 87 16:04:16 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Thanks for the comments. I hope the others will comment as well (but
I'm certainly willing to wait a few days).
If multiple initargs that fill the same slot are supplied, which value ends up
in the slot is indeterminate.
In what sense do you mean "indeterminate"? Do you mean "defined to be
one of those values, but not defined as to which of them", such that it
would be legal to use a random number generator to decide?
Yes. "which value" should be "which of those values". I certainly won't complain
if someone proposes a determinate action here instead.
We could check, at run time for make-instance that two initargs that fill
the same slot are not getting a value.
For the constructors, we can check at compile time that they don't specify in
their lambda list two initargs filling the same slot. This would be a
restriction for constructors.
Those are good ideas. I agree with the constructor one. I'm not so sure about
the make-instance one, because I just noticed that Common Lisp allows duplicate
keyword arguments in a function call and mandates that the leftmost argument
prevails. One could argue that this should extend to arguments that have different
names but fill the same slot.
I was concerned about the speed of a runtime check either to do what you
(Patrick) suggested, or to do what I just mentioned above. However,
after consulting our implementation I see that it is easy to do,
although we are not currently using the mechanism to address the issue
of multiple initargs filling the same slot. Briefly, you detect at
compile time (or the first time a class is instantiated) that there are
multiple possible initargs, and then you assign a bit in a bit mask to
record whether the given slot has been filled. If you see an initarg
that fills a slot whose bit is already set, you either ignore it
(leftmost duplicate prevails) or check what keyword was used the
previous time (signal an error except in the case where Common Lisp says
the leftmost duplicate prevails).
Given all this, I added the following to my proposal (philosophy section):
>> What if multiple initargs that fill the same slot are supplied?
If the same initarg is given more than once in the arguments to make-instance,
the leftmost occurrence prevails, as required by Common Lisp.
If two different initargs that fill the same slot are given in the arguments
to make-instance, the leftmost occurrence prevails (alternatively we could
make this an error, but I think it's simpler to treat it the same as two
occurrences of the same initarg).
A :constructor option whose lambda-list has more than one parameter that
fills a single slot signals an error, whether or not the parameter names
are eq (see proposal below for how it is possible for non-eq parameters
to fill the same slot).
I also added the following related clarification:
When :default-initargs defaults an initarg that
fills a slot, it is treated the same as an :initform slot-option for purposes
of inheritance (note well: the class that specifies the :default-initargs
may not know whether the initarg fills a slot or not, and indeed this may
depend on which subclass of that class we are dealing with). If a single
class specifies more than one default value for a single slot, via
:default-initargs or :initform or both, an error is signalled.
Is this agreeable?
Initargs don't have to be keywords, but the entire object creation might not work
very well if any of initargs is not a keyword:
In common Lisp, :allow-other-keys T works only for keyword value pairs. We would
have to slightly change its meaning for make-instance.
In practice this is probably implemented by calling all of the
initialize-instance methods with all of the initargs and automatically adding
&allow-other-keys to the lambda-list in defmethod.
This won't work if there is an initarg which is not a key. The methods that
can be called during object creation (like those on allocate-instance) would be
easier to code if they knew that they would get keyword-value pairs. (if I
understand correctly, those methods would get all the arguments supplied to
make-instance, right?)
I can't understand what you're getting at here. Could you send a follow-up
message this is more explicit?
>> Can step 2 return an existing object instead of allocating storage,
aborting the remaining steps?
No, to do "interning" you must build a higher-level interface around
make-instance. Make-instance always makes.
I am wondering if you propose to enforce this. What if somebody defines an
:around method for ALLOCATE-INSTANCE and does not call-next-method but returns
an interned object instead ? Is it an error?
I don't see how it would be possible to enforce a restriction that the value
returned by ALLOCATE-INSTANCE is not EQ to any other object in the world.
However, note that in your example the value returned by ALLOCATE-INSTANCE
is going to have every one of its slots stored into, and is going to have
its INITIALIZE-INSTANCE methods run, so the effect might not be what the user
intended. What I was really getting at with my philosophy question is "should
a way be provided for the metaclass to be able to completely bypass the
entire action of MAKE-INSTANCE?" and my answer to that is "no". In my file
copy of the proposal I changed this section to the following:
>> Can step 2 return an existing object instead of allocating storage,
aborting the remaining steps?
Step 2 can return anything it wants, but the remaining steps are still
executed. To do "interning" you must build a higher-level interface around
make-instance; make-instance always makes. No way is provided for the
metaclass to be able to completely bypass the entire action of MAKE-INSTANCE.
Is this agreeable?
∂17-Apr-87 1244 Moon@STONY-BROOK.SCRC.Symbolics.COM (long) CLOS Declaration Proposal Text
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 17 Apr 87 12:44:29 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 118986; Fri 17-Apr-87 15:29:48 EDT
Date: Fri, 17 Apr 87 15:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: (long) CLOS Declaration Proposal Text
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8704162339.AA22952@hplabsc>
Message-ID: <870417152924.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
This is a good beginning. Not being a fan of machines that require
declarations, I'm going to keep a low profile in this discussion, but
I do have a couple of comments/criticisms for you.
5) If method combination is prohibited for a certain method,
any overhead which is needed to support method combination
in the general case could be avoided.
I agree that this is a non-issue.
(CLASS FOO X)
I think (EXACT-CLASS FOO X) has a lot less potential for confusion.
a user may want to restrict a particular name to be a generic function
I don't see why. I suggest leaving this out unless there is a good
reason for it (which should be articulated).
When a user creates a subclass of a "staticized" class, rather than
changing the semantics in some unclear way, I suggest signalling an
error if there is a conflict between the semantics frozen into the
superclass and the semantics that would exist if the superclass had not
been "staticized". The design principle here is that adding a
"staticize" declaration to a working program shouldn't change what it
does, only how fast it does it.
The name MAKE-STATIC isn't the best. To me, it connotes a function that
returns an object that I can hand to the WRITE-SOUND function and get an
ugly noise from the speaker in my console. FREEZE-CLASS would be better.
∂20-Apr-87 1331 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 20 Apr 87 13:31:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae19504; 20 Apr 87 16:13 EDT
Received: from ti-csl by RELAY.CS.NET id ax17675; 20 Apr 87 16:05 AST
Received: from Jenner (jenner.ARPA) by tilde id AA16384; Mon, 20 Apr 87 14:48:44 cdt
Message-Id: <2754935345-480598@Jenner>
Date: Mon, 20 Apr 87 14:49:05 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
In-Reply-To: Msg of Fri, 17 Apr 87 14:49 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Fri, 17 Apr 87 14:49 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Re: Object creation discussion (at last!)
>> What if multiple initargs that fill the same slot are supplied?
If the same initarg is given more than once in the arguments to make-instance,
the leftmost occurrence prevails, as required by Common Lisp.
If two different initargs that fill the same slot are given in the arguments
to make-instance, the leftmost occurrence prevails (alternatively we could
make this an error, but I think it's simpler to treat it the same as two
occurrences of the same initarg).
A :constructor option whose lambda-list has more than one parameter that
fills a single slot signals an error, whether or not the parameter names
are eq (see proposal below for how it is possible for non-eq parameters
to fill the same slot).
I also added the following related clarification:
When :default-initargs defaults an initarg that
fills a slot, it is treated the same as an :initform slot-option for purposes
of inheritance (note well: the class that specifies the :default-initargs
may not know whether the initarg fills a slot or not, and indeed this may
depend on which subclass of that class we are dealing with). If a single
class specifies more than one default value for a single slot, via
:default-initargs or :initform or both, an error is signalled.
Is this agreeable?
Yes.
Initargs don't have to be keywords, but the entire object creation might not work
very well if any of initargs is not a keyword:
In common Lisp, :allow-other-keys T works only for keyword value pairs. We would
have to slightly change its meaning for make-instance.
In practice this is probably implemented by calling all of the
initialize-instance methods with all of the initargs and automatically adding
&allow-other-keys to the lambda-list in defmethod.
This won't work if there is an initarg which is not a key. The methods that
can be called during object creation (like those on allocate-instance) would be
easier to code if they knew that they would get keyword-value pairs. (if I
understand correctly, those methods would get all the arguments supplied to
make-instance, right?)
I can't understand what you're getting at here. Could you send a follow-up
message this is more explicit?
Take the following example:
(make-instance 'class-1 'SLOT1 2 :AREA 'class-1-area 'JUNK 3
:allow-other-keys t)
SLOT-1 is an initarg for a slot, :AREA is a key for an allocate-instance
method, but JUNK is not a valid initarg. According to your proposal,
:allow-other-keys would tell make-instance to ignore JUNK (ie. return
without signalling an error). In Common Lisp :allow-other-keys T
does not apply to non-keywords like JUNK.
Suppose I have a method like:
(defmethod allocate-instance ((class 'class-1) &key :area
&allow-other-keys)
.....)
If we call allocate-instance with all the initarg-value pairs coming
from the make-instance call and if all the initargs are keywords, then
according to Common Lisp, only the :area keyword is not ignored and we
get the intended effect.
Now, if one of the initargs is not a keyword, then Common Lisp says it
is an error...
My point is, the implementations will have to filter out non keyword
initargs that are not relevant to allocate-instance before calling
allocate-instance if they want strict compliance with CLtL. Is this
true or did I miss something?
>> Can step 2 return an existing object instead of allocating storage,
aborting the remaining steps?
Step 2 can return anything it wants, but the remaining steps are still
executed. To do "interning" you must build a higher-level interface around
make-instance; make-instance always makes. No way is provided for the
metaclass to be able to completely bypass the entire action of MAKE-INSTANCE.
Is this agreeable?
Yes.
∂20-Apr-87 1355 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Apr 87 13:55:34 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 120069; Mon 20-Apr-87 16:55:30 EDT
Date: Mon, 20 Apr 87 16:55 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Object creation discussion (at last!)
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2754935345-480598@Jenner>
Message-ID: <870420165517.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 20 Apr 87 14:49:05 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Date: Fri, 17 Apr 87 14:49 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
I can't understand what you're getting at here.
In Common Lisp :allow-other-keys T
does not apply to non-keywords like JUNK.
I can't find any evidence for this except at the top of p.62 in CLtL where
it says "It is an error for the first object of each pair to be anything
but a keyword." I was under the impression that it had been decided a
couple of years ago that the last word in this sentence should have been
"symbol", but perhaps that's not true. Unfortunately I lost my copy, but
I think this was in the proposed corrections and clarifications Guy Steele
distributed in December 1985.
If only symbols in the keyword package are allowed as keyword argument
names, my object creation proposal falls apart, as does every other one
that has ever been mailed to this list! I tell you what I'll do; I'll
go find out the format for submissions to the cleanup subcommittee and
send this in. Let's proceed on the assumption that it will be accepted.
∂20-Apr-87 1449 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 20 Apr 87 14:48:49 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad20964; 20 Apr 87 17:45 EDT
Received: from ti-csl by RELAY.CS.NET id ap18098; 20 Apr 87 17:37 AST
Received: from Jenner (jenner.ARPA) by tilde id AA19015; Mon, 20 Apr 87 16:10:24 cdt
Message-Id: <2754940257-775701@Jenner>
Date: Mon, 20 Apr 87 16:10:57 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
David,
Another small point:
I did a census of :before and :after :init methods on our system:
There are 864 flavors,
192 :before :init methods,
336 :after :init methods.
The :after :init methods seem to be more common than :before :init.
Did you come up with a different count?
Patrick.
∂21-Apr-87 0812 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 21 Apr 87 08:12:20 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab05835; 21 Apr 87 11:06 EDT
Received: from ti-csl by RELAY.CS.NET id ab23071; 21 Apr 87 11:00 AST
Received: from Jenner (jenner.ARPA) by tilde id AA02583; Tue, 21 Apr 87 07:44:11 cdt
Message-Id: <2754996278-4141536@Jenner>
Date: Tue, 21 Apr 87 07:44:38 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
In-Reply-To: Msg of Mon, 20 Apr 87 16:55 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 20 Apr 87 16:55 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Re: Object creation discussion (at last!)
Date: Mon, 20 Apr 87 14:49:05 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Date: Fri, 17 Apr 87 14:49 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
I can't understand what you're getting at here.
In Common Lisp :allow-other-keys T
does not apply to non-keywords like JUNK.
I can't find any evidence for this except at the top of p.62 in CLtL where
it says "It is an error for the first object of each pair to be anything
but a keyword." I was under the impression that it had been decided a
couple of years ago that the last word in this sentence should have been
"symbol", but perhaps that's not true. Unfortunately I lost my copy, but
I think this was in the proposed corrections and clarifications Guy Steele
distributed in December 1985.
I didn't find any reference to this in the clarifications/corrections.
I tell you what I'll do; I'll go find out the format for
submissions to the cleanup subcommittee and send this in. Let's
proceed on the assumption that it will be accepted.
Sounds good.
∂21-Apr-87 1049 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Apr 87 10:49:03 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 120677; Tue 21-Apr-87 13:40:33 EDT
Date: Tue, 21 Apr 87 13:40 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Object creation discussion (at last!)
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2754940257-775701@Jenner>
Message-ID: <870421134012.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 20 Apr 87 16:10:57 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
I did a census of :before and :after :init methods on our system:
There are 864 flavors,
192 :before :init methods,
336 :after :init methods.
The :after :init methods seem to be more common than :before :init.
Did you come up with a different count?
When I make these counts I try to exclude the window system, because I
don't consider its design representative of how things would be programmed
today. Unless you've redesigned the MIT window system a lot more than we
have, that's probably true of your system as well.
Here are the make-instance methods I found (in my CLOS object creation
proposal these would be initialize-instance methods, and I have translated
the method qualifiers to the terminology of that proposal):
224 methods total
138 unqualified methods
81 :after methods
5 :around methods
I expected the fraction of :after methods to be lower than 36%. I suppose
it would be good to study them and see why so many are being used, but that
would take more time than I wish to spend today. Maybe later.
For completeness, here are the :init counts, but they are mostly window
flavors:
293 methods total
92 :before methods
23 unqualified methods
170 :after methods
8 :around methods
There is the same preponderance of :after methods, but because :init uses
:daemon method combination (thus almost anything that uses an unqualified
method is, in fact, broken) and because of the influence of the window
system, I don't think there is much to be learned from these numbers.
∂22-Apr-87 1348 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 13:48:21 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 APR 87 13:44:58 PDT
Date: Wed, 22 Apr 87 13:42 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422134241.3.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
I have a lot of comments and questions about this proposal. I
originally tried to work them in with the running text, but that proved
too cumbersome given the general nature of my comments. What's more,
this message itself isn't all that polished. I thought it would be
better to send it out now so that you would have an idea of what I was
thinking.
My overall comment is that this proposal is a lot more complicated than
either of my previous proposals, in fact it doesn't seem to stress
simplicity at all.
Parts of this proposal provide important, useful and understandable
functionality, which I would like to see in CLOS. Other parts add
considerable conceptual complexity and don't seem to add significant
functional gain. The best example of this is the special method
combination type for initialize-instance.
After I send out this message I will begin working on another message
which lays out the framework of a proposal which incorporates all the
things I really like about your proposal. I think that will be the best
way to make it clear what I have in mind.
My major objections are with:
*** special method combination for the initialize-instance
The special method combination type for initialize instance adds
considerable conceptual overhead for very little functional gain.
I admit that the basic method combination rule is simple enough to
understand. But there are other aspects of this method combination
types which will cause people to ask themeselves questions they will
have a hard time answering with any kind of simple model of this thing.
- if I don't have to say &allow-other-keys here, why do I have to
say it in the normal kind of method combination?
- why is it that I can't count on the methods getting all the initargs
if I use &rest in the lambda-list? Note that this also robs useful
functionality which exists everywhere else in Common Lisp. Specifically,
it makes the &rest args &allow-other-keys idiom not work. This idiom
is very useful for methods which want to process all the initargs in
the init-plist in ways that makes those initargs interact.
- If I redefine a initialize-instance method, will that effect the
interpretation of all the :constructor lambda-lists involved? Will
all those :constructors get fixed?
*** the complex rules for interpreting the lambda-list of :constructors
These rules are just plain complicated. In order to figure out what to
do, you need to know:
The names of all the slots, inherited and local (simple enough).
All the mappings to initargs of those slot names. Inheriting
this information is simple enough, but name mapping is confusing
in general.
All the :default-initargs inherited and local. Once again,
understanding the inheritance here is simple enough.
But putting all this together is pretty complicated. Because it isn't
really three simple inheritance structures that are then combined. I
don't think? I think your rules may cover the following case, but I
don't believe its that simple to reason about.
(defclass foo ()
()
(:default-initargs :bazola ()))
(defclass bar (foo)
((b :initarg :bazola)))
(defclass baz ()
()
(:constructor make-baz (&key bazola)))
(defmethod initialize-instance ((a-baz baz) &key bazola)
(setf (slot-value a-baz 'b) (list bazola (slot-value a-baz 'b))))
*** the overemphasis on getting speed out of the :constructors.
This proposal seems to be mostly focused on getting speed out of using
the :constructors. While I agree that instance creation speed is
important, I am not sure that I like putting so much emphasis on doing
it using :constructors.
For one thing, from the user's point of view, I don't believe it is easy
to understand why constructors should be so much faster. I don't
believe that the reasons why the :constructors are so much faster are
obvious.
For another thing, the ability to be able to compile the :constructors
into something fast leaks all over. The rule that says that particular
initialize-instance methods can't count on getting the entire set of
initargs is an excellent example of this "leakage".
Other specific questions:
- what arguments does allocate-instance get? at one point you say:
From Moon:
2. Initargs that control storage allocation are defined by defining an
allocate-instance method that accepts the initarg as an &key argument.
For example, in systems with areas :area is an initarg for step 2.
The standard does not require any initargs to exist for step 2.
but how does this work? why don't all the allocate instance methods
also have to say &allow-other-keys.
Things that I like and agree with:
Since I have been focusing on things I don't like, it may not be clear
what I do like. Let me try to make explicit some of the major points I
like and agree with.
I like the functionality provided by the :default-initargs option. The
next proposal I will submit has this feature in a slighltly more
CommonLispy syntax.
I agree that the initargs to make instance are "more abstract" than slots.
I agree that constructors should call initialization methods.
I agree that it is important for instance creation to be fast. I agree
that :constructors are the best known way of doing this.
I agree that there should be no defclass option which specifies an
initarg for all the slots.
I probably agree with other, more subtle things that I don't remember
right now.
-------
∂22-Apr-87 1448 Gregor.pa@Xerox.COM CL types --> classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 14:48:35 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 22 APR 87 14:48:02 PDT
Date: Wed, 22 Apr 87 14:46 PDT
From: Gregor.pa@Xerox.COM
Subject: CL types --> classes
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422144631.4.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
This message is a brief summary of what I believe we decided about which
Common Lisp types could be classes. This is take from Sonya's very
careful notes and my less careful memory. If we pass this message back
and forth for a while it could probably become a draft of a section in
the design rationale document.
I plan to send something like this (hopefully after it is improved by
the other people on this list) to the CommonLoops list to explain the
changes I am making in built-in classes in the next release of PCL.
Take table 4-1 from CLtL (page 43). From that table, the following
types do NOT have corresponding classes:
ATOM
This is a negation type.
STANDARD-CHAR STRING-CHAR BIT FIXNUM BIGNUM
We decided not to do subranges.
COMMON STREAM FUNCTION
Specification in CLtL too vague. It would be nice if X3J13 fixed stream
and function though.
KEYWORD
Class can change by setf of symbol-package.
SIMPLE-ARRAY SIMPLE-BIT-VECTOR SIMPLE-STRING SIMPLE-VECTOR
?? What is the reason for this ??
PACKAGE READTABLE RANDOM-STATE HASH-TABLE PATHNAME
CLtL only requires that these types be disjoint with each other. We
would like X3J13 to fix these too.
SHORT-FLOAT LONG-FLOAT SINGLE-FLOAT DOUBLE-FLOAT
I don't believe we excluded these but I believe either Pavel or Patrick
said they would write up the rules about how these work.
-------
∂22-Apr-87 1533 Pavel.pa@Xerox.COM Re: CL types --> classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 15:33:09 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 APR 87 15:19:17 PDT
Date: 22 Apr 87 15:19 PDT
From: Pavel.pa@Xerox.COM
Subject: Re: CL types --> classes
In-reply-to: Gregor.pa's message of Wed, 22 Apr 87 14:46 PDT
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422-151917-4178@Xerox>
SHORT-FLOAT LONG-FLOAT SINGLE-FLOAT DOUBLE-FLOAT
I don't believe we excluded these but I believe either Pavel or
Patrick said they would write up the rules about how these work.
I indeed said that I would write these up. I'll be able to get to it later this week.
Pavel
∂22-Apr-87 1637 Gregor.pa@Xerox.COM note about clos instance disjointness
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 16:37:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 APR 87 16:37:59 PDT
Date: 22 Apr 87 16:37 PDT
From: Gregor.pa@Xerox.COM
Subject: note about clos instance disjointness
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422-163759-4304@Xerox>
I don't know exactly where this would fit in in the document, but we
need to say that instances of standard-classes have type disjoint with
all other types. This is kind of obvious of course, but should be made
explicit.
∂22-Apr-87 1639 Gregor.pa@Xerox.COM funcallable-standard-class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 16:39:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 APR 87 16:40:52 PDT
Date: 22 Apr 87 16:40 PDT
From: Gregor.pa@Xerox.COM
Subject: funcallable-standard-class
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422-164052-4316@Xerox>
Another note just to record something we all need to think about.
We need to document the metaclass which generic-function classes use.
This is so that people can define their own generic-function classes
(the need to know what :metaclass to specify).
Also, the funcallable-instance functionality is useful enough, and easy
enough to document that I think we should make it generally available.
This note will serve to remind me to mail out a proposal about this
based on what is now in PCL.
∂22-Apr-87 1729 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Apr 87 17:29:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 APR 87 17:30:04 PDT
Date: Wed, 22 Apr 87 17:28 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870422172838.5.GREGOR@AVALON.isl.parc.xerox.com>
Line-fold: no
OK, here is a try at a counter proposal which tries to show what I do
and don't like about your proposal. This isn't finished yet, once again
I thought it would be better to send it out now so that you could see
where I was headed.
Basically, my proposal keeps these features from your proposal:
:initarg slot option
:default-initargs defclass option (different syntax)
make-instance processes slot initargs or evaluates initforms
constructors can be faster because they can inline stuff
and gets rid of these:
the new method combination type for initialize instance
using &key in an initialize-instance method augments legal initargs
SO:
The :initarg slot option can be used to teach make-instance the name of
an initarg which can be used to initialize the value of this slot from
the initargs passed to make-instance. The way to think of this option
is that it implements the abstract initarg name to slot name mapping for
make-instance. For convenience, specifying an :initarg name in a slot
description also includes that initarg name in the :default-initargs of
the defclass.
The default-initargs defclass option serves two purposes. It specifies
all the initargs which can be passed to make-instance of this class, and
it specifies default values for some of those initargs. The syntax of
this option is a lot like the part of a lambda-list following &key
(which serves two similar purposes). For example:
(:default-initargs :foo :bar (:baz 3))
says that this class accepts initargs :FOO, :BAR and :BAZ. Furthermore,
the default value of the :BAZ initarg is 3. The default values of :FOO
and :BAR are both nil.
So, a defclass form like this:
(defclass position ()
((x :initarg :x)
(y :initarg :y))
(:default-initargs (:x 0) (:y 0) :rho :theta))
can be read as saying: make-instance with a first argument of POSITION
accepts 4 initargs (:x :y :rho :theta). The default value for :x and :y
is 0; the default value for :rho and :theta is nil. When make-instance
is called, it sets the value of the x slot of the instance to the value
of the :x initarg ..(same for y and :y).
make-instance calls allocate-instance generic-function with all the
initargs (the ones passed to make-instance plus any defaulted ones). It
then sets the values of any slots for which initargs appear in the
initargs, it then sets the values of the remaining slots from their
initforms. It then calls the intialize-instance generic-function with
all the initargs.
constructors can be thought of as providing a "boa" syntax for specific
calls to make-instance. Because make-instance is a function and not a
generic-function, constructors are allowed to "perform the same actions
calling make-instance would have" rather than calling make-instance
directly. As a result, in many implementations, constructors are faster
than the corresponding call to make-instance. To produce the "call to
make-instance" a constructor interprets its lambda-list as follows:
- if an element of its lambda-list names an initarg acceptable to
this class, then that initarg pair will appear in the "call to
make-instance".
- if an element of the lambda list does not name an initarg, but
names a slot this is an abbreviation for defining a gensymed initarg
for that slot and using that gensym.
[This needs work or perhaps need to be removed. I want to try
to make this case be an abbreviation for something that is
already understood.]
- if neither of the above are true, calling the constructor signals
an error. Some implementations may warn earlier of course.
initialize-instance uses the default kind of method combination. Note
that all initialize-instance methods should say &allow-other-keys.
Under some programming styles, many initialize-instance methods will be
:before methods. Under other programming styles they will not be, they
will probably use call-next-method.
-------
∂23-Apr-87 0953 kempf%hplabsc@hplabs.HP.COM Re: CLOS Type Cleanup
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 23 Apr 87 09:51:39 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 23 Apr 87 08:13:56 pst
Received: by hplabsc ; Thu, 23 Apr 87 08:14:08 pst
Date: Thu, 23 Apr 87 08:14:08 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8704231614.AA11598@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: CLOS Type Cleanup
Gregor's list looks accurate.
One comment on FUNCTION. If X3J13 fixes this, then a nice solution
about what to do with funcallable instances might be to make them
a subclass of FUNCTION.
jak
∂23-Apr-87 1225 kempf%hplabsc@hplabs.HP.COM Re: (long) CLOS Declaration Proposal Text
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 23 Apr 87 12:25:23 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 23 Apr 87 09:10:55 pst
Received: by hplabsc ; Thu, 23 Apr 87 09:09:09 pst
Date: Thu, 23 Apr 87 09:09:09 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8704231709.AA12554@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: (long) CLOS Declaration Proposal Text
Some additional comments on the declaration discussion,
and Moon's reply. Dick Gabrial, are you still there?
> 5) If method combination is prohibited for a certain method,
> any overhead which is needed to support method combination
> in the general case could be avoided.
>
>I agree that this is a non-issue.
OK, then, unless anyone else objects, we can drop any consideration
of declarations for method combination.
> (CLASS FOO X)
>
>I think (EXACT-CLASS FOO X) has a lot less potential for confusion.
This syntax is fine with me.
> a user may want to restrict a particular name to be a generic function
>
>I don't see why. I suggest leaving this out unless there is a good
>reason for it (which should be articulated).
I would like to see this resolved in the context of the GFLET,
GFLABELS, and GLAMBDA proposals discussed earlier. In particular,
I would like the ability to say:
(MAPCAR <some local generic function> LIST-OF-OBJECTS)
and not have to do a global definition of the methods. A GENERIC-FUNCTION
declaration might allow us to get away without introducing GFLET
and GFLABELS. For example, the following could be legal:
(DEFUN EXAMPLE (OBJECT-LIST)
(FLET
(FOO ((A FOO-CLASS)) A)
(FOO ((B BAZ-CLASS)) B)
)
(DECLARE (GENERIC-FUNCTION FOO))
(MAPCAR #'FOO OBJECT-LIST)
)
or some similar syntax. Notice that this will not resolve the problem
of GLAMBDA, however.
>When a user creates a subclass of a "staticized" class, rather than
>changing the semantics in some unclear way, I suggest signalling an
>error if there is a conflict between the semantics frozen into the
>superclass and the semantics that would exist if the superclass had not
>been "staticized". The design principle here is that adding a
>"staticize" declaration to a working program shouldn't change what it
>does, only how fast it does it.
I agree here.
>The name MAKE-STATIC isn't the best. To me, it connotes a function that
>returns an object that I can hand to the WRITE-SOUND function and get an
>ugly noise from the speaker in my console. FREEZE-CLASS would be better.
I like the idea of using FREEZE-<something> for optimization and other
postdevelopment processing. I would suggest the following additions to
the metaobject protocol for this purpose:
FREEZE-REDEFINITION <class>
Takes a class object as an argument and causes the definition of the
class to be frozen. Any attempt to redefine the class will cause an
error to be signalled. In order for a class's definition to be frozen,
all superclass definitions must be frozen as well. An error will be
signalled if this is not the case.
FREEZE-SLOT-LAYOUT <class>
Causes slots to be located at fixed offsets if the class is used as
a superclass during inheritence. Signals an error if all superclasses
do not have frozen slot layout as well.
FREEZE-CLASS-PRECEDENCE-LIST <class>
The class precedence list for the class argument is calculated (if
it hasn't already been) and the class precedence for subclasses
is frozen. An attempt to define a subclass whose included direct
supers would cause a difference class precedence ordering causes
an error to be signalled. An error is signalled if all superclasses
of the class argument do not have frozen class precedence lists
as well.
jak
∂23-Apr-87 1249 kempf%hplabsc@hplabs.HP.COM Re: Object Creation Discussion (at last!)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 23 Apr 87 12:48:38 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 23 Apr 87 08:02:47 pst
Received: by hplabsc ; Thu, 23 Apr 87 08:03:20 pst
Date: Thu, 23 Apr 87 08:03:20 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8704231603.AA11434@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Object Creation Discussion (at last!)
Comments on Moon's creation note (and subsequent discussion):
OVERALL COMMENTS:
I agree with Gregor that the proposal needs simplification. The
special method combination type, the overemphasis on constructor
speed (they could be simply declared IN-LINE) and the complex
rules for lambda-list interpretation need some reworking.
In addition, I would like to see the syntax for the :INITFORM, :INITARG,
and :DEFAULT-INITARG options better integrated (see below for addition to
Gregor's suggestion).
SPECIFICS:
*On symbols as initarg keys:
> "initargs" (initialization arguments) are a set of named arguments that
> control object creation and initialization. Each initarg has a name, which
> is a symbol (not necessarily a keyword), and a value. The arguments to
> make-instance, excepting the first, taken in pairs, are initargs.
Subsequent discussion has cleared up this point as a potential area
of incompatibility which needs a cleanup committee proposal.
*On storage allocation:
> Also customizable by the metaclass, because the metaclass controls the
> stored representation of instances.
This should probably be the "recommended" way of doing things.
Though it's probably not a good idea to prohibit it, I think it
should be encouraged for portability reasons. The metaobject protocol
should be the lowest level, portable interface into the object system.
Anything below should be system dependent.
*On the proposed additional slot and class definition options:
>3. Customizable by slot-description, which specifies a default value for the
> slot and whether the slot can be filled with a value specified by the
> client; if so, the slot-description specifies the name of the initarg
> whose value is stored into the slot.
>The :default-initargs defclass option is followed by alternating initarg
>names and forms. If an initarg is not specified by the client nor by
>a :default-initargs option in a more specific class, the form is evaluated
>in the lexical environment of the defclass and the resulting value is used
>for the initarg.
From subsequent discussion, it seems as if an additional DEFCLASS
option, :DEFAULT-INITARGS is being proposed. I wonder if this
is needed, considering that a user can already specify an initialization
value via the :INITFORM option? Perhaps the metaclass ought to
attend to this? Or the :INITFORM and :DEFAULT-INITARGS options should
be merged?
In particular:
>So, a defclass form like this:
>
> (defclass position ()
> ((x :initarg :x)
> (y :initarg :y))
> (:default-initargs (:x 0) (:y 0) :rho :theta))
>
Consider what the syntax would be if you wanted to specify an initform
as well:
(defclass position ()
((x :initarg :x :initform 0)
(y :initarg :y :initform 0))
(:default-initargs (:x 0) (:y 0) :rho :theta))
So why not simplify this as:
(defclass position ()
((x :initarg (:x 0))
(y :initarg (:y 0)))
( <some appropriate key> :rho :theta)
)
Semantics are:
1) If MAKE-INSTANCE is called without an initialization list,
the initialization values of X and Y are set to zero.
2) If initialization values are supplied in the initialization list,
then they are used.
3) :RHO and :THETA are valid as keys for initargs to MAKE-INSTANCE in
any case. If no value is given, then they are NIL.
A suggestion for <some appropriate key> would be :ADDITIONAL-INITARGS.
*On MAKE-INSTANCE and modules:
>>> Is make-instance an intra-module or inter-module interface?
>
>Both.
>
>>> Do the arguments to make-instance correspond directly to actual stored
>slots, or are they a more abstract concept, whose implementation in terms
>of slots or in terms of something else is hidden from the caller?
>
>More abstract, because make-instance is often used as an inter-module
I don't understand. What is understood here by the word "module"?
Has it any relation to *MODULES* on pg. 188 and thus to the
PROVIDE/REQUIRE mechanism?
*On constructors:
>>> What is the lambda-list of a constructor created by a :constructor
>option with no lambda-list specified?
>
>It accepts the same arguments as make-instance, excepting the first.
>
>>> Do constructors call initialization methods?
>
>Yes.
>
>>> Why do we have a :constructor option to defclass?
>
>For speed; make-instance is interpretive, while constructors are compiled,
>since they know the exact class that they are constructing, and since they can
>be automatically recompiled if the class or any of its superclasses changes.
I'm not quite sure how this fits in with the metaclass protocol.
What if a user defines a constructor function to make an object out
of a list, or to return a symbol? If the constructor function tries
to call initializaton methods, then what will be the result? Also,
if the initialization succeeds, method definition and lookup might
do the wrong thing if the low level structure of an instance is
not what is expected. As an example, say the constructor function
returns an integer, and there are two methods on a generic function,
one with an INTEGER selector and one with the same class as the
erring constructor function.
In addition, I think the IN-LINE declaration could help getting speed
out of a constructor.
*On the context in which an initialization is run:
>The :initarg slot-option specifies that this slot can be filled in, and
>specifies the initarg name. This slot-option can be given more than once.
>
>There is no defclass option that specifies initargs for all the slots,
>because that would endorse a particular convention for naming initargs.
>
Are the initforms run in the context of INITIALIZE-INSTANCE? Is WITH-SLOTS
acceptable within an initform?
I think this proposal would satisfy Dave Martin's request for initialization
hooks. I'm enclosing his message on this below.
jak
---------------------------------------------------------------------------
Well, what we currently have is the following:
defmethod initialize ((self new-object) init-plist)
(initialize-from-defaults self)
(initialize-from-init-plist self init-plist)
(apply #'new-instance self init-plist))
Where the new-instance function is defined to do nothing for new-object but
takes an arbitrary list of keywords (generally including slot names) to
set the values.
What I would *like* to see is the function initialize (or some other name)
initialize from the defaults, and then initialize from the init-plist only
on slots keywords (this is what we do, I rewrote initialize-from-init-plist
to ignore non-keyword slots) and then call a class specific function to
do the remaining setup. It would be nice if slots which were read-only
were still settable inside the initialization code (e.g. the resource id of
a window object should be read-only, but I can't set it until the new-instance
function is called).
I was thinking about changing the initialize function to do the following:
1) initialize from the default value of each keyword slot; 2) use the setf
function for setting from the init-plist argument for any keywords which
correspond to slots; and 3) call a user-specifiable routine (i.e. have a slot
in the class called initialize-method) which would be mandatory for each class
and would be hacked to allow call-next-method to find the appropriate method
for the super classes even if the method name differed.
With this setup we avoid having to set aside new-instance as a reserved
name, allow the system to set slot values appropriately (using the setf method
should be a flaggable option), and hopefully be able to reduce the size
of the new-instance function.
∂23-Apr-87 1456 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CLOS Declaration Proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Apr 87 14:56:52 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 123315; Thu 23-Apr-87 17:53:57 EDT
Date: Thu, 23 Apr 87 17:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: CLOS Declaration Proposal
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8704231709.AA12554@hplabsc>
Message-ID: <870423175345.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
The only problem with using functions, rather than defclass options,
to freeze attributes of classes is how to make these functions take
effect at compile time, which is when they have to take effect to be
of any use. Propose something.
∂23-Apr-87 1722 kempf%hplabsc@hplabs.HP.COM Re: CLOS Declaration Proposal
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 23 Apr 87 17:22:03 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 23 Apr 87 15:38:10 pst
Received: by hplabsc ; Thu, 23 Apr 87 15:27:22 pst
Date: Thu, 23 Apr 87 15:27:22 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8704232327.AA18524@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: CLOS Declaration Proposal
Cc: common-lisp-object-system@sail.stanford.edu
I understand the problem. I can see two possible solutions.
1) Introduce a declaration which invokes the metaclass functions.
Something like:
(PROCLAIM '(FREEZE-CLASS-PRECEDENCE-LIST FOO))
in the DEFSYS file would cause the class precedence list to be
frozen.
2) Leave it up to use of (EVAL-WHEN (COMPILE EVAL) ... ) to
do it.
I don't like either of these much, but like a defclass option even
less, since there are already so many.
I'll give it some more thought. Thanks for pointing this out.
jak
∂23-Apr-87 2020 Gregor.pa@Xerox.COM Re: Object Creation Discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Apr 87 20:20:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 APR 87 18:24:27 PDT
Date: 23 Apr 87 18:24 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object Creation Discussion (at last!)
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Thu,
23 Apr 87 08:03:20 pst
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870423-182427-1534@Xerox>
Date: Thu, 23 Apr 87 08:03:20 pst From: Jim Kempf
<kempf%hplabsc@hplabs.HP.COM>
From subsequent discussion, it seems as if an additional
DEFCLASS option, :DEFAULT-INITARGS is being proposed. I wonder if
this is needed, considering that a user can already specify an
initialization value via the :INITFORM option? Perhaps the
metaclass ought to attend to this? Or the :INITFORM and
:DEFAULT-INITARGS options should be merged?
I don't think we have reduced initialization to its fundamental
components yet. In this message I am trying to attack some of our
assumptions to see if that can help us get at those fundamental
components.
What if we got rid of :initform??
What is the purpose of :initform anymore? You only need it when you
want to specify the default value for a slot that isn't set by any
initarg. This means that we have two mechanisms which do almost the
same thing -- initargs which set slots are almost a superset of
initforms. This is a sure sign of bad modularity.
Let's just pretend you didn't have initforms but that you did want to be
able to have some slots which had "default values" but which weren't
initable from the initargs passed to make-instance.
(in the terminology of all previous proposals:
(defclass position () ((x 0) (y 0)))
now, adopting a slighlty different syntax for :default-initargs, you
could say:
(defclass position ()
(x
y)
(:default-initargs (:moosefish1 0 x)
(:moosefish2 0 y)))
(apologies to Alan Snyder)
This new syntax for default-initargs reads:
":moosefish1 is an initarg whose default value is 0 and which
make-instance
uses to set the value of the x slot..."
:moosefish1 is some name which is chosen to be weird enough that no-one
will ever use it. So, "in-effect" the slots are not initable in the
call to make-instance. When the initialize-instance generic-function is
called (whether that call is open coded or not) the values of the x and
y slots are sure to be 0.
:moosefish1 is silly of course (more apologies to Alan), but what about
something like:
(defclass position ()
(x
y)
(:default-initargs (nil 0 x)
(nil 0 y)))
What I am trying to do is seperate what I perceive as the separate parts
of what is going on into separate places.
1. the structure of the instance is specified, the slots and their
allocation.
2. the legal initarg names are specified
3. the default values for the initargs are specified
4. automatic initialization of the values of some of the slots by
make instance is specified.
the slot descriptions specify 1 (the structure of the instance)
the cars of the :default-initargs option arguments specify the legal
initarg names
the cadrs specify the default value
the caddrs specify which slots are set from the value.
think of the :default-initargs syntax as being something like the syntax
of what follows &key in a lambda list except reversed, so each can be
one of:
initarg | (initarg default-value) | (initarg default-value slot-name)
∂23-Apr-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM CL types --> classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Apr 87 21:32:39 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 123676; Fri 24-Apr-87 00:32:46 EDT
Date: Fri, 24 Apr 87 00:32 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: CL types --> classes
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870422144631.4.GREGOR@AVALON.isl.parc.xerox.com>
Message-ID: <870424003237.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 22 Apr 87 14:46 PDT
From: Gregor.pa@Xerox.COM
My notes generally agree with your message. Here are the differences
and extensions:
They say COMPILED-FUNCTION is in the same boat with FUNCTION.
KEYWORD
Class can change by setf of symbol-package.
There was an argument about whether Common Lisp allows setf of
symbol-package, but I think we came up with a way to use IMPORT to
change something that isn't a keyword into a keyword. Traditionally
the type of an object is something you can't change. Does the
existence of CHANGE-CLASS mean that KEYWORD should be a class?
I feel like leaving out KEYWORD on the basis that extra classes
shouldn't be put in if they aren't clearly useful, but this is an
issue that could go either way.
SIMPLE-ARRAY SIMPLE-BIT-VECTOR SIMPLE-STRING SIMPLE-VECTOR
?? What is the reason for this ??
Subrange is scrawled next to these on my notes. If these are
subranges then KEYWORD is too.
PACKAGE READTABLE RANDOM-STATE HASH-TABLE PATHNAME
CLtL only requires that these types be disjoint with each other. We
would like X3J13 to fix these too.
There are probably a lot of implementations in which one or more of these
is a subtype of ARRAY. That might be hard to fix efficiently?
No list type-specifier names a class and no deftype names a class, say
my notes.
SHORT-FLOAT LONG-FLOAT SINGLE-FLOAT DOUBLE-FLOAT
I don't believe we excluded these but I believe Pavel
said he would write up the rules about how these work.
The issue was that if there are methods defined for both
SHORT-FLOAT and SINGLE-FLOAT, but these types are collapsed into
one, the precedence order of the methods is not well-defined.
The only thing we thought of in the meeting was to signal an error
when this happens, but I suspect that would be unsatisfactory in
practice.
In the precedence relationships for built in classes with
multiple direct superclasses, I think we decided on
(defclass null (list symbol) ...)
(defclass vector (array sequence) ...)
(defclass list (cons sequence) ...)
Are we ready to write this up yet?
∂26-Apr-87 2231 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 Apr 87 22:30:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 124868; Mon 27-Apr-87 01:31:17 EDT
Date: Mon, 27 Apr 87 01:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation discussion (at last!)
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870416002258.1.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870421134012.6.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870422134241.3.GREGOR@AVALON.isl.parc.xerox.com>,
<870422172838.5.GREGOR@AVALON.isl.parc.xerox.com>,
<8704231603.AA11434@hplabsc>,
<870423-182427-1534@Xerox>
Message-ID: <870427013057.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
I can see from the misunderstanding in the mail that I did an abysmal job
of communicating my ideas. I'll try to send a more comprehensible essay
tomorrow, but for now I would like to just clarify a couple of points and
then make some comments on excerpts from the mail in places where they
might help communication.
Complexity and simplicity are partly matters of taste, and largely matters
of point of view. I try to take the point of view of the majority of
programmers, who are using the outer interfaces of the system without
necessarily understanding everything that's going on inside. No matter how
beautifully we explain it, most programmers simply won't read beyond the
point where they think they know everything they need to know to get their
immediate job done. Now, it may be that we will decide that we would
rather make life more complicated for people writing initialization methods
in order to make the conceptual explanation shorter. That would be okay
with me if it's done for good reasons, but we shouldn't just dismiss the
other way without understanding it and understanding why I proposed it. I
have a feeling this message isn't going to explain it adequately either,
and if that happens I will apologize and follow up with a more carefully
written explanation.
One key point that I was trying to convey, and I think partially succeeded,
was the need for information hiding (abstraction) in the arguments to
make-instance and in relations among the various initialization
specifications attached to a class and its superclasses.
Another key point, which I don't think came through, was that each initarg
should be explicitly defined, and should be defined in exactly one place.
This is simply good modularity.
Some aspects of what I proposed were reacting to user complaints about the
way Flavors does it. I have the ambition of making this new standard
better than Flavors.
All this leads to the idea that initargs of types 2 and 4 (in the
nomenclature of my 16 Apr message) should be defined by methods, since
their meaning is implemented by methods. Similarly, type 3 should be
defined by slot-options, since their meaning is entirely involved with
slots. In Flavors, type 4 have the ugly property that they have to be
defined in two places, once in the method that implements them and again in
a defflavor form; it's easy to get these two places out of sync. Hence the
proposal to use the lambda-list of a defmethod as the way to define these
initargs. Along with this, I tried to eliminate clunky syntax from
initialization methods, hence the elimination of &allow-other-keys and the
elimination of having to write :before all the time. If this is too
confusing, we could invent a new syntax that both defines initargs and
defines the method that implements them. Clearly this is the weakest part
of my proposal.
We could obviously simplify things a lot by getting rid of the :constructor
option to defclass. I didn't put it in, at least not this year. I do think
it ought to remain, in spite of its inherent complexity in any initialization
proposal (previous ones I've seen have glossed over this rather than solving
it), because I believe many users will find it quite useful.
Date: Wed, 22 Apr 87 13:42 PDT
From: Gregor.pa@Xerox.COM
The special method combination type for initialize instance adds
considerable conceptual overhead for very little functional gain.
The goal was not functional gain, that is, the ability to program something
you couldn't program before, but rather syntactic simplicity. Perhaps in
the end we'll decide it's not worth it, but I'd like us to keep considering
the question a bit longer.
I admit that the basic method combination rule is simple enough to
understand. But there are other aspects of this method combination
types which will cause people to ask themeselves questions they will
have a hard time answering with any kind of simple model of this thing.
- if I don't have to say &allow-other-keys here, why do I have to
say it in the normal kind of method combination?
True, this is a problem.
- why is it that I can't count on the methods getting all the initargs
if I use &rest in the lambda-list? Note that this also robs useful
functionality which exists everywhere else in Common Lisp. Specifically,
it makes the &rest args &allow-other-keys idiom not work. This idiom
is very useful for methods which want to process all the initargs in
the init-plist in ways that makes those initargs interact.
I can't figure out precisely all you're saying here, but I think this just
stems from a half-baked idea that I wouldn't have included in the proposal
if I had spent more time thinking about it before sending it. I was trying
to do an efficiency optimization involving not consing lists of slot-filling
initargs that have been defaulted, and I now think that was premature. We
can revisit the question after the major framework is agreed upon, plus I
always (except when I fall from grace) believe in the principle that designs
should first consider what is right, and optimizations should be subordinate
to that, fitting into an existing framework rather than distorting it.
- If I redefine a initialize-instance method, will that effect the
interpretation of all the :constructor lambda-lists involved? Will
all those :constructors get fixed?
Of course the constructors have to get fixed if you change something in a
way that changes the compiled code that was supposed to have been generated
for them. I think that fact is independent of details of all object
creation proposals. The specific example that I think you were thinking
about is when a positional parameter of a constructor is changed from
something that only fills a slot and isn't cared about by initialize
methods, to something that both fills a slot and is seen by initialize
methods. In my proposal, adding an initialize-instance method could do
this. In your most recent one, evaluating a defclass could do this.
*** the complex rules for interpreting the lambda-list of :constructors
.... example elided ....
I don't see any problem here that I added. The lambda-list syntax of
constructors is like defstruct, not like defun, but that's already in
87-002.
Your example also touches upon the lambda-list of initialize-instance
methods. Here the default for an argument that is already defaulted by
defclass options would never be used, because all calls that reached the
initialize-instance method would necessarily have to supply that argument.
But I don't think there's anything new to Common Lisp in that.
- what arguments does allocate-instance get?
allocate-instance was intended to work exactly like initialize-instance,
however the latter turns out.
Date: Wed, 22 Apr 87 17:28 PDT
From: Gregor.pa@Xerox.COM
The default-initargs defclass option serves two purposes. It specifies
all the initargs which can be passed to make-instance of this class, and
it specifies default values for some of those initargs.
This is an important modularity mistake, in my opinion. By combining these
two things, which ought to be separate, you have lost the ability for one
class to specify a default value for an initarg defined by another class.
If specifying a default value always defines an initarg, there is no way to
check the consistency of the set of initargs with default values specified
against the set of initargs actually defined. If there is a misspelling,
the default value will simply be discarded, since no method will receive it
and do something with it.
constructors can be thought of as providing a "boa" syntax for specific
calls to make-instance.
This can't work as long as constructors are allowed to fill slots that
make-instance is not allowed to fill, which I think is an important ability
because it gives the programmer more control over interfaces.
Date: Thu, 23 Apr 87 08:03:20 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
From subsequent discussion, it seems as if an additional DEFCLASS
option, :DEFAULT-INITARGS is being proposed. I wonder if this
is needed, considering that a user can already specify an initialization
value via the :INITFORM option? Perhaps the metaclass ought to
attend to this? Or the :INITFORM and :DEFAULT-INITARGS options should
be merged?
This indicates that I completely failed to convey what :default-initargs is
about, and that in turn may possibly indicate that :default-initargs should
be flushed. In my proposal there are two ways to specify a default for an
initarg: at the point of definition, and remotely. To explain: when
defining an initarg one can specify right there, locally, a default value
form. For initargs that fill slots, this is the existing :initform
slot-option; no need to invent anything new there. For initargs that are
implemented by methods, this is the existing defaulting mechanism in the
lambda-list; again, no need to invent anything new. Now for remote
defaulting: here the idea is that one class defines what an initarg means,
while a second class specifies a default for it; this is :default-initargs.
When you mix the two classes together, the default meets up with the
implementation and things work. The reason remote defaulting is desirable
is twofold: (1) it's often useful when mixing classes together for one
class to customize another class by specifying initialization options, in
addition to the existing ability to customize a class by shadowing or
wrapping methods; (2) for modularity reasons, when class A customizes class
B by specifying an initarg that class B defines, class A shouldn't have to
know whether the initarg fills a slot or is implemented by a method. If
not for reason (2), remote defaulting wouldn't require a new mechanism,
because it could be implemented using the existing mechanism of :initform
for slot initargs plus call-next-method-with-arguments (proposed but not
yet accepted) for method initargs. But I think reason (2) is important.
I don't understand. What is understood here by the word "module"?
Has it any relation to *MODULES* on pg. 188 and thus to the
PROVIDE/REQUIRE mechanism?
No relation. I meant the general computer-science concept of modules as
subdivisions of a program that have some independence from each other, not
something realized as an object in an implementation.
What if a user defines a constructor function to make an object out
of a list, or to return a symbol? If the constructor function tries
to call initializaton methods, then what will be the result? Also,
if the initialization succeeds, method definition and lookup might
do the wrong thing if the low level structure of an instance is
not what is expected. As an example, say the constructor function
returns an integer, and there are two methods on a generic function,
one with an INTEGER selector and one with the same class as the
erring constructor function.
In addition, I think the IN-LINE declaration could help getting speed
out of a constructor.
By "constructor", I meant the functions defined by the :constructor option
to defclass. The syntax of that option doesn't admit any of the above
possibilities.
I wonder if you were getting at a different issue: what if the value
returned by the allocate-instance method is not an instance of the exact
class being instantiated? If the caller of allocate-instance simply
assumes the type of this value is correct, all kinds of terrible things
could happen, especially if slot-filling is open-coded in constructors.
Danny's chapter 3 speaks of "recognizable blocks of storage", and I think
we need to say something like that here. I think this issue is largely
independent of the other details of object creation proposals, and needs to
be resolved on its own. It's hard for me to say much about it since I don't
understand why anyone would need to customize allocate-instance.
Are the initforms run in the context of INITIALIZE-INSTANCE?
We agreed some time ago that they are in the lexical environment in which
the defclass was evaluated.
Is WITH-SLOTS acceptable within an initform?
WITH-SLOTS works everywhere (although it works more efficiently in some
places). However, the object being created is not lexically available in
the environment of initforms, so it isn't possible to access its slots.
Some people have proposed that the object and the initargs be lexically
available to initforms, and this does open some intriguing expressive
possibilities. However, I think I prefer to say that anything this
complicated should be done in initialize-instance methods instead.
Date: 23 Apr 87 18:24 PDT
From: Gregor.pa@Xerox.COM
What is the purpose of :initform anymore? You only need it when you
want to specify the default value for a slot that isn't set by any
initarg. This means that we have two mechanisms which do almost the
same thing -- initargs which set slots are almost a superset of
initforms. This is a sure sign of bad modularity.
On the contrary, I think it's a sign of good modularity! The two
mechanisms do almost the same thing inside the implementation, but from the
point of view of someone on the outside who doesn't know the information
that is supposed to be hidden from him by modular abstraction, they do
rather different things. I could give a longer explanation of what I mean,
but it's late, this message is already too long to ask anyone to read
carefully, and I think I would just be repeating what I said a bit earlier.
(defclass position ()
(x
y)
(:default-initargs (nil 0 x)
(nil 0 y)))
What I am trying to do is seperate what I perceive as the separate parts
of what is going on into separate places.
The reason I don't like this is that the information about a slot is no
longer all in one place. Another way of saying it is that I think that
information in defclass should be organized spatially rather than
temporally, i.e. information pertaining to one slot should be together,
rather than putting information pertaining to one phase of object creation
together. One of the ways that I think defclass is better than defflavor
is that it has done a better job of spatial organization by putting more
of the information about a slot into slot options instead of scattering it
around in various options some of which refer back to the slot by name.
∂27-Apr-87 1329 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Apr 87 13:29:14 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab26381; 27 Apr 87 16:20 EDT
Received: from ti-csl by RELAY.CS.NET id ah07490; 27 Apr 87 16:17 EDT
Received: from dsg (juliett.ARPA) by tilde id AA04504; Mon, 27 Apr 87 14:27:09 cdt
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Mon, 27 Apr 87 14:28:46 CDT
Message-Id: <2755538893-1609268@Jenner>
Date: Mon, 27 Apr 87 14:28:13 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
In-Reply-To: Msg of Mon, 27 Apr 87 01:30 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 27 Apr 87 01:30 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Object creation discussion (at last!)
I can see from the misunderstanding in the mail that I did an abysmal job
of communicating my ideas. I'll try to send a more comprehensible essay
tomorrow, but for now I would like to just clarify a couple of points and
then make some comments on excerpts from the mail in places where they
might help communication.
Complexity and simplicity are partly matters of taste, and largely matters
of point of view. I try to take the point of view of the majority of
programmers, who are using the outer interfaces of the system without
necessarily understanding everything that's going on inside. No matter how
beautifully we explain it, most programmers simply won't read beyond the
point where they think they know everything they need to know to get their
immediate job done. Now, it may be that we will decide that we would
rather make life more complicated for people writing initialization methods
in order to make the conceptual explanation shorter. That would be okay
with me if it's done for good reasons, but we shouldn't just dismiss the
other way without understanding it and understanding why I proposed it. I
have a feeling this message isn't going to explain it adequately either,
and if that happens I will apologize and follow up with a more carefully
written explanation.
One key point that I was trying to convey, and I think partially succeeded,
was the need for information hiding (abstraction) in the arguments to
make-instance and in relations among the various initialization
specifications attached to a class and its superclasses.
Another key point, which I don't think came through, was that each initarg
should be explicitly defined, and should be defined in exactly one place.
This is simply good modularity.
Some aspects of what I proposed were reacting to user complaints about the
way Flavors does it. I have the ambition of making this new standard
better than Flavors.
All this leads to the idea that initargs of types 2 and 4 (in the
nomenclature of my 16 Apr message) should be defined by methods, since
their meaning is implemented by methods. Similarly, type 3 should be
defined by slot-options, since their meaning is entirely involved with
slots. In Flavors, type 4 have the ugly property that they have to be
defined in two places, once in the method that implements them and again in
a defflavor form; it's easy to get these two places out of sync. Hence the
proposal to use the lambda-list of a defmethod as the way to define these
initargs.
I would stress this point further by saying that an object system is
going to be appreciated for its ease of use during program development.
Adding a new method is a normal thing to do and will be easier
(faster,...) on most implementation than DEFCLASS redefinition which is
a more traumatic operation (potential obsolescence of class...). Adding
a new initarg keyword to make-class for 2 or 4 does not make the class
obsolete. We shouldn't be forced to reevaluate DEFCLASS for such a small
and upwardly compatible change.
Date: Thu, 23 Apr 87 08:03:20 pst
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
From subsequent discussion, it seems as if an additional DEFCLASS
option, :DEFAULT-INITARGS is being proposed. I wonder if this
is needed, considering that a user can already specify an initialization
value via the :INITFORM option? Perhaps the metaclass ought to
attend to this? Or the :INITFORM and :DEFAULT-INITARGS options should
be merged?
This indicates that I completely failed to convey what :default-initargs is
about, and that in turn may possibly indicate that :default-initargs should
be flushed. In my proposal there are two ways to specify a default for an
initarg: at the point of definition, and remotely. To explain: when
defining an initarg one can specify right there, locally, a default value
form. For initargs that fill slots, this is the existing :initform
slot-option; no need to invent anything new there. For initargs that are
implemented by methods, this is the existing defaulting mechanism in the
lambda-list; again, no need to invent anything new. Now for remote
defaulting: here the idea is that one class defines what an initarg means,
while a second class specifies a default for it; this is :default-initargs.
When you mix the two classes together, the default meets up with the
implementation and things work. The reason remote defaulting is desirable
is twofold: (1) it's often useful when mixing classes together for one
class to customize another class by specifying initialization options, in
addition to the existing ability to customize a class by shadowing or
wrapping methods; (2) for modularity reasons, when class A customizes class
B by specifying an initarg that class B defines, class A shouldn't have to
know whether the initarg fills a slot or is implemented by a method. If
not for reason (2), remote defaulting wouldn't require a new mechanism,
because it could be implemented using the existing mechanism of :initform
for slot initargs plus call-next-method-with-arguments (proposed but not
yet accepted) for method initargs. But I think reason (2) is important.
Date: 23 Apr 87 18:24 PDT
From: Gregor.pa@Xerox.COM
What is the purpose of :initform anymore? You only need it when you
want to specify the default value for a slot that isn't set by any
initarg. This means that we have two mechanisms which do almost the
same thing -- initargs which set slots are almost a superset of
initforms. This is a sure sign of bad modularity.
On the contrary, I think it's a sign of good modularity! The two
mechanisms do almost the same thing inside the implementation, but from the
point of view of someone on the outside who doesn't know the information
that is supposed to be hidden from him by modular abstraction, they do
rather different things. I could give a longer explanation of what I mean,
but it's late, this message is already too long to ask anyone to read
carefully, and I think I would just be repeating what I said a bit earlier.
(defclass position ()
(x
y)
(:default-initargs (nil 0 x)
(nil 0 y)))
What I am trying to do is seperate what I perceive as the separate parts
of what is going on into separate places.
The reason I don't like this is that the information about a slot is no
longer all in one place. Another way of saying it is that I think that
information in defclass should be organized spatially rather than
temporally, i.e. information pertaining to one slot should be together,
rather than putting information pertaining to one phase of object creation
together. One of the ways that I think defclass is better than defflavor
is that it has done a better job of spatial organization by putting more
of the information about a slot into slot options instead of scattering it
around in various options some of which refer back to the slot by name.
I see :default-initargs being on the client side (make-instance and
such) and :initform being on the implementor side. One will supersede the
other, but conceptually they are different and should be kept different.
∂29-Apr-87 1836 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Apr 87 18:35:58 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 127851; Wed 29-Apr-87 21:36:13 EDT
Date: Wed, 29 Apr 87 21:36 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation discussion (at last!)
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870427013057.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870429213604.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 27 Apr 87 01:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I can see from the misunderstanding in the mail that I did an abysmal job
of communicating my ideas. I'll try to send a more comprehensible essay
tomorrow....
As you can see, I didn't get to it. I'm not going to be allowed that kind of
time for this until some time next week, so if you have comments but you were
waiting for that before sending them, open fire.
∂06-May-87 0936 kempf%hplabsc@hplabs.HP.COM Printing Objects
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 6 May 87 09:35:59 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 6 May 87 09:33:39 pdt
Received: by hplabsc ; Wed, 6 May 87 09:34:12 pdt
Date: Wed, 6 May 87 09:34:12 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705061634.AA12121@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Printing Objects
Looking through the PRINT-OBJECT specification, there is no read macro
specified for allowing an object printed out to be read back in.
Since DEFSTRUCT has the #S read macro, it seems as if something similar
should be available for instances of classes of the default metaclass.
#O comes to mind first, but, of course, that is used by octal numbers.
Why not #@? From CLTL, pg. 352, this one looks free.
Jim Kempf kempf@hplabs.hp.com
∂06-May-87 1142 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Printing Objects
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 6 May 87 11:42:06 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa15417; 6 May 87 14:35 EDT
Received: from ti-csl by RELAY.CS.NET id ab23481; 6 May 87 14:31 EDT
Received: from Jenner (jenner.ARPA) by tilde id AA17350; Wed, 6 May 87 13:09:25 cdt
Message-Id: <2756311822-982351@Jenner>
Date: Wed, 6 May 87 13:10:22 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Jim Kempf <kempf%hplabsc@hplabs.hp.com>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Printing Objects
In-Reply-To: Msg of Wed, 6 May 87 09:34:12 pdt from Jim Kempf <kempf%hplabsc@hplabs.hp.com>
Date: Wed, 6 May 87 09:34:12 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.hp.com>
Subject: Printing Objects
Looking through the PRINT-OBJECT specification, there is no read macro
specified for allowing an object printed out to be read back in.
Since DEFSTRUCT has the #S read macro, it seems as if something similar
should be available for instances of classes of the default metaclass.
#O comes to mind first, but, of course, that is used by octal numbers.
Why not #@? From CLTL, pg. 352, this one looks free.
Jim Kempf kempf@hplabs.hp.com
I don't see why #S couldn't be extended to read instances. Since #S
can only read "typed" structures (those that define a common lisp type),
the semantics wouldn't get changed.
∂06-May-87 1304 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 6 May 87 13:03:08 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 6 May 87 13:00:01 pdt
Received: by hplabsc ; Wed, 6 May 87 13:00:33 pdt
Date: Wed, 6 May 87 13:00:33 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705062000.AA15399@hplabsc>
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET, kempf%hplabsc@hplabs.hp.com
Subject: Re: Printing Objects
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
> Date: Wed, 6 May 87 09:34:12 pdt
> From: Jim Kempf <kempf%hplabsc@hplabs.hp.com>
> Subject: Printing Objects
>
> Looking through the PRINT-OBJECT specification, there is no read macro
> specified for allowing an object printed out to be read back in.
> Since DEFSTRUCT has the #S read macro, it seems as if something similar
> should be available for instances of classes of the default metaclass.
> #O comes to mind first, but, of course, that is used by octal numbers.
>
> Why not #@? From CLTL, pg. 352, this one looks free.
>
> Jim Kempf kempf@hplabs.hp.com
>
>I don't see why #S couldn't be extended to read instances. Since #S
>can only read "typed" structures (those that define a common lisp type),
>the semantics wouldn't get changed.
>
That would be OK too. Looking at the specification of #S, it could
be extended to anything with a constructor. The important point is
that the extension be noted in the CLOS specification, so it doesn't
get lost.
Jim Kempf kempf@hplabs.hp.com
∂06-May-87 2024 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Printing Objects
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 May 87 20:24:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 133775; Wed 6-May-87 23:22:56 EDT
Date: Wed, 6 May 87 23:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Printing Objects
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <8705062000.AA15399@hplabsc>
Message-ID: <870506232253.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 6 May 87 13:00:33 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
> Date: Wed, 6 May 87 09:34:12 pdt
> From: Jim Kempf <kempf%hplabsc@hplabs.hp.com>
>
> Looking through the PRINT-OBJECT specification, there is no read macro
> specified for allowing an object printed out to be read back in.
>
>I don't see why #S couldn't be extended to read instances. Since #S
>can only read "typed" structures (those that define a common lisp type),
>the semantics wouldn't get changed.
That would be OK too. Looking at the specification of #S, it could
be extended to anything with a constructor. The important point is
that the extension be noted in the CLOS specification, so it doesn't
get lost.
If we wanted a thing like #S for instances of standard classes, we would
certainly use #S rather than inventing another read macro that does the
same thing as #S. However, there are some problems with #S.
Since we seem to be agreeing that the technique for creating objects
will not make the physical slots directly visible, but instead will add
a layer of abstraction, there is the issue that this transformation
may not be reversible: It may not be self-evident how to convert the
slot-values of an object into a set of arguments to make-instance that
will create an object with the same slot-values. Suppose that not all
of the slots have initargs that can initialize them.
If instead we made #S bypass make-instance's abstraction and specify
the physical slots directly, it would be a terrible violation of
modularity. What this really shows, I think, is that only a method
for the class in question can know what is the proper way to create
an equivalent instance.
In addition to this issue of slot values, I don't think the concept
of "allowing an object printed out to be read back in" is well-defined,
because the concept of reading "the same object" is not well-defined.
In the simplest cases, creating an object of the same class with
slot values "printed out and read back in" will do the job, but only
in the simplest cases. In general, an object is part of a data structure
and ripping the object out of that data structure and jamming it
into a world by itself may not be meaningful. This is the same reason
why we don't provide a general copy-object function.
I think it would make sense to have a standardized mixin class for
those simple objects whose semantics are defined entirely by the
values of their initializable slots. This class would define a
print-object method that used either #S(...) or #.(make-instance ...),
and would probably also define methods for copying and for dumping
into binary files output by compilers. This is fine; the thing I
want to be very cautious about is assuming that -all- objects should
have these methods. It's much better to package them in a mixin that
is there if you want it and not otherwise. Any suggestions for a
good name for this class? simple-object?
∂06-May-87 2202 Masinter.pa@Xerox.COM Re: Printing Objects
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 May 87 22:02:34 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 06 MAY 87 22:00:14 PDT
Date: 6 May 87 22:01 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Printing Objects
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 6 May 87 23:22 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870506-220014-1229@Xerox>
Of the alternatives:
a) All objects print out as #S, if you want different behavior, you
override it
b) By default, objects can't print themselves, and you have to provide a
print function or else mixin a standard class
Consider three cases:
1) object wants to print out as #S...
2) object cannot be printed really -- it doesn't make sense to "read" it
3) object wants to be printed in a special way
Case 1: a is preferable, since what you want to do is already the
default
Case 2: b is only marginally better. In alternative a, you have to
supply an error-if-you-print-me method or else you will get printing
when you shouldn't really --if your erroneously print something and
try to read it back in, alternative b gives you an error at print time,
while alternative a gives you an error later on in your program.
Case 3: it makes no difference, since you're supplying a print method.
I think Case 1 is the most common in most of the program's I've seen
anyway.
∂06-May-87 2235 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Printing Objects
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 May 87 22:35:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 133838; Thu 7-May-87 01:33:56 EDT
Date: Thu, 7 May 87 01:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Printing Objects
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870506-220014-1229@Xerox>
Message-ID: <870507013351.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 6 May 87 22:01 PDT
From: Masinter.pa@Xerox.COM
Of the alternatives:
a) All objects print out as #S, if you want different behavior, you
override it
b) By default, objects can't print themselves, and you have to provide a
print function or else mixin a standard class
This is misleading. 87-002 requires that the implementation provide a default
method. The issue in question is not whether objects can print themselves,
but what happens you feed the output of that to read. Thus alternative b
should be stated as "By default, objects print something that signals an error
when read." If I wanted to be parallel to that, but biased, I would state
alternative a as "By default, objects print something that creates a bogus
object when read."
Consider three cases:
1) object wants to print out as #S...
2) object cannot be printed really -- it doesn't make sense to "read" it
3) object wants to be printed in a special way
Case 1: a is preferable, since what you want to do is already the
default
Case 2: b is only marginally better. In alternative a, you have to
supply an error-if-you-print-me method or else you will get printing
when you shouldn't really --if your erroneously print something and
try to read it back in, alternative b gives you an error at print time,
while alternative a gives you an error later on in your program.
Not so, since Common Lisp is missing the :readably argument to WRITE.
Alternative b gives you an error at read time, not print time.
Case 3: it makes no difference, since you're supplying a print method.
I think Case 1 is the most common in most of the program's I've seen
anyway.
Not in the programs I've seen. Leaving aside endless arguments about who's
seen what programs, and turning to design rationales: I think it is better
to signal an error when there is some question what people might want,
and provide a way for them to say what they want, than to lead them down
a garden path that ends up in a mysterious blowout because the system
guessed their intention wrong. This is a general principle, but I think
it applies to this case.
∂07-May-87 0851 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 7 May 87 08:50:58 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 7 May 87 07:49:32 pdt
Received: by hplabsc ; Thu, 7 May 87 07:49:54 pdt
Date: Thu, 7 May 87 07:49:54 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705071449.AA25199@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Printing Objects
Leaving aside the question of whether to use #S and how to match
reading to MAKE-INSTANCE, couldn't the *PRINT-ESCAPE* switch play
a role about whether an object is printed out in a form which
is readable again? My reading of the description of *PRINT-ESCAPE*
on pg. 370 of CLtL is not clear. The first paragraph seems to
imply that this switch is supposed to primarily affect printing
of symbols with strange print names, the second paragraph seems
to imply that it serves a more general function in controlling
whether a "structure" (and by this I interpret CLtL to mean
any Common Lisp data structure, not just a DEFSTRUCT) gets printed
in a way which makes it readable again. Perhaps this switch could
be used for controlling whether the instance is printed in a
readable or nonreadable form.
Returning to the more general question, while I agree about the
desirability for compiling objects into a binary form and writing
them out, and other forms of saving objects, these will all be
machine dependent. Looking at other object-oriented languages,
one of the most attractive aspects of Objective-C to many programmers
is the Filer, a way of writing an object out in ASCII form. It provides
a kind of "lowest common denominator" persistence, and is a debugging
aid too. A programmer can send a Filer generated representation of
an Objective-C object around a local area network of diverse machines
without much extra code to do conversion from one form to another.
On the question of reading violating abstraction and who should
know how to print out an object, I think it is the metaclass rather
than the class which should know about how to print an object and
read it again. The metaclass controls the low level representation
of the object, thus should have the knowledge to decompose and write
it out, and read it in again. For FUNCALLABLE-STANDARD-CLASS, for
example, the metaclass method could do the same thing as is done
for a fundef. For STANDARD-CLASS, a default method could be provided
to read and write the object. Other metaclasses would need to supply
their own methods.
This should not, however, preclude a programmer from defining a method
on a class which writes an object in some nonreadable form.
I also agree that any read macro should go through MAKE-INSTANCE, to
avoid violating the class/object abstraction. Maybe some combination
of #S and #. could play a role, or maybe the default is simply:
#.(make-instance (class-named <name of class> <init-plist))
I think that it is important for this issue to be put into the
language spec once we have resolved it. With current Common Lisp,
there are a number of nonstandard read macros for creating the
underspecified types (e.g. #P for pathnames), which are
springing up due to need.
Jim Kempf kempf@hplabs.hp.com
∂13-May-87 1131 kempf%hplabsc@hplabs.HP.COM Object Printing Discussion
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 13 May 87 11:30:14 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 13 May 87 08:56:07 pdt
Received: by hplabsc ; Wed, 13 May 87 08:56:15 pdt
Date: Wed, 13 May 87 08:56:15 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705131556.AA06328@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Object Printing Discussion
Continuing the object printing discussion, I'd like to address
some points brought up by Moon, and summarize things so far.
Before going further, however, I'd like to provide some
motivation for continuing
this discussion. As mentioned in a previous note, the Objective-C Filer has
proven to be a useful tool for Objective-C programmers, even though it does
have some serious disadvantages as a mechanism for storing objects.
Additionally, CommonObjects never defined a default
storage mechanism (primarily because
the issues of abstraction violation were not fully thought out) and it has
proven to be a perennial problem. Binary storage mechanisms based on compiler
modifications, databases and the like are all interesting, but some base
level hooks and a simple default storage mechanism using existing Common Lisp
read macros where possible and ASCII text can simplify applications development
and provide backward compatibility with DEFSTRUCT. I'm sure, if it is
not provided, someone will to question why DEFSTRUCT's have
a readable storage representation and objects do not.
On to the discussion:
>Since we seem to be agreeing that the technique for creating objects
>will not make the physical slots directly visible, but instead will add
>a layer of abstraction, there is the issue that this transformation
>may not be reversible: It may not be self-evident how to convert the
>slot-values of an object into a set of arguments to make-instance that
>will create an object with the same slot-values. Suppose that not all
>of the slots have initargs that can initialize them.
I agree with the need for a layer of abstraction, however, the level of
MAKE-INSTANCE may be too high. In particular, if, as Moon's comments indicate,
the defined initialization protocol for the class will not accomodate
initializing an object with the current slot value when read back in,
it would not be possible to write out an object's slot values and read
them back in using MAKE-INSTANCE. An example would be when no initarg
is defined for a slot (i.e., it is not initializable from MAKE-INSTANCE).
>In addition to this issue of slot values, I don't think the concept
>of "allowing an object printed out to be read back in" is well-defined,
>because the concept of reading "the same object" is not well-defined.
>In the simplest cases, creating an object of the same class with
>slot values "printed out and read back in" will do the job, but only
>in the simplest cases. In general, an object is part of a data structure
>and ripping the object out of that data structure and jamming it
>into a world by itself may not be meaningful. This is the same reason
>why we don't provide a general copy-object function.
I think you could make this argument for any Lisp data structure, including
lists, vectors, or what have you. Perhaps more strongly for objects, since
they tend to be more highly structured. I certainly agree it may not be
meaningful to write out an object and read it back in, but, in the default
case, I think the metaclass could provide some kind of meaning, which
could then be customized on a class by class (or metaclass by metaclass)
basis. In cases where it is not possible to provide meaning (like
writing out packages and fundefs in Common Lisp), the #< read macro
can be used to prohibit reading the representation back in.
>I think it would make sense to have a standardized mixin class for
>those simple objects whose semantics are defined entirely by the
>values of their initializable slots. This class would define a
>print-object method that used either #S(...) or #.(make-instance ...),
>and would probably also define methods for copying and for dumping
>into binary files output by compilers. This is fine; the thing I
>want to be very cautious about is assuming that -all- objects should
>have these methods. It's much better to package them in a mixin that
>is there if you want it and not otherwise. Any suggestions for a
>good name for this class? simple-object?
As mentioned in a previous note, I think that control of object representation
should be left to the metaclass, and therefore this functionality should
be part of the metaobject protocol. The metaobject protocol controls how
objects and classes get created within memory, and thus it seems logical
that it should also control how objects move out to disc.
. . . . . .
Lacking any concensus on object creation, it's difficult to outline a
detailed proposal as to what should be done. Here's a summary of
my thinking on the issue so far:
1) CLOS should specify a default printable object representation which
is readable again, if only because programmers find it useful.
2) This representation should be ASCII and should use existing Common Lisp
read macros where possible, to facilitate portability and backward
compatibility.
3) The abstraction level should be below MAKE-INSTANCE, so that slots
which are not initable through MAKE-INSTANCE initargs can still be
initialized, but above the level of simply setting the slot, so the
class can customize initialization from a dumped object if desired.
4) The hooks should be part of the metaobject protocol, since the
metaobject protocol controls the representation of classes and
instances.
With regard to 3) and 4), possibly the issue of conversion of slot
values could be dealt with via a method on the STANDARD-SLOT-DESCRIPTION
class. However, I'll forgo any detailed proposals until hearing whether
there is any agreement about the overall issues.
Jim Kempf kempf@hplabs.hp.com
∂13-May-87 1323 Gregor.pa@Xerox.COM Re: Object Printing Discussion
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 May 87 13:22:56 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 13 MAY 87 12:51:11 PDT
Date: 13 May 87 12:50 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object Printing Discussion
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Wed,
13 May 87 08:56:15 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870513-125111-2498@Xerox>
Be warned, I am going to (mostly) dump on using printing for dumping.
The reason defstruct has a readable representation for printed objects
is because defstruct is broken in this (and many other) regard. I
believe the default printed representation of defstruct types lulls
programmers into a false sense of believing that the problem of dumping
and restoring has been solved for them when in fact, that is not at all
true.
In my mind, printing an object for the user read its 'printed
representation' and dumping an object so that some other program can
restore it later are two completely different operations. In addition,
depending on the application or mode, there may be many different ways
to do each of these.
Lets just look at dumping/restoring, what are some of the issues:
- circularity, how to deal with it?
- pointers to special "ground" objects which shouldn't be dumped but
which
should be "re-grounded" when the object is restored.
- restoring an object but not all the objects it points to
None of these questions is terribly hard, but they all have very
different answers depending on the specific application. Whats more,
none of these have to do with efficiency per se. I can add efficeincy
as another problem, it only makes this more complicated.
- efficiency of dump format. Certainly the #S format is about the least
efficient
dump format imaginable. It takes a lot of space, and it takes a lot
of work at
dump and restore time.
So I guess my opinion is that it would be a mistake to try to
standardize a 'generally useful for dumping' print function. Certainly
any class or metaclass which wants to can provide a different method for
print-object which would be the base of a whole dumping/restoring
sub-protocol. So the hook is there for people to do whatever they want.
But I think we would be doing them a diservice to pretend that we had
provided them a general solution to this problem.
Here is a related question?
What happens if an object appears as a constant in a piece of code that
is being compiled to a file? CLtL certainly is not clear on what
happens if a defstruct-defined structure appears in such a place. Is
print-object what you would like to call here??
∂13-May-87 1444 DLW@ALDERAAN.SCRC.Symbolics.COM Object Printing Discussion
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 13 May 87 14:44:22 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 81287; Wed 13-May-87 17:31:55 EDT
Date: Wed, 13 May 87 17:31 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Object Printing Discussion
To: kempf%hplabsc@hplabs.HP.COM, common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8705131556.AA06328@hplabsc>
Message-ID: <870513173115.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Wed, 13 May 87 08:56:15 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
1) CLOS should specify a default printable object representation which
is readable again, if only because programmers find it useful.
The point is that it's not clear what "readable" means, and how useful
it is. You'd have to be more careful about how this is defined. What
if the value of one of the slots is a compiled code object? But even if
all the values are symbols, you still have to make sure that people
realize that reading this printed representation can only be said to
"create a new instance which, in some respects, is like the instance
that got printed", which isn't really guaranteeing very much.
2) This representation should be ASCII and should use existing Common Lisp
read macros where possible, to facilitate portability and backward
compatibility.
(Not ASCII, but the CL character set, which is more restrictive than
that. Portability to the 370, remember.)
4) The hooks should be part of the metaobject protocol, since the
metaobject protocol controls the representation of classes and
instances.
I don't agree with this; it would be a real pain in the neck, and
overkill, to have to define a whole new metaclass just to say how an
instance is printed. Defining a method is far easier.
∂14-May-87 1322 kempf%hplabsc@hplabs.HP.COM Re: Printing Objects
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 14 May 87 13:22:01 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 14 May 87 13:21:05 pdt
Received: by hplabsc ; Thu, 14 May 87 13:21:23 pdt
Date: Thu, 14 May 87 13:21:23 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705142021.AA26108@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Printing Objects
Cc: kempf%hplabsc@hplabs.HP.COM
From Gregor:
>Be warned, I am going to (mostly) dump on using printing for dumping.
>
>The reason defstruct has a readable representation for printed objects
>is because defstruct is broken in this (and many other) regard. I
>believe the default printed representation of defstruct types lulls
>programmers into a false sense of believing that the problem of dumping
>and restoring has been solved for them when in fact, that is not at all
>true.
From Dan Weinreb:
> 4) The hooks should be part of the metaobject protocol, since the
> metaobject protocol controls the representation of classes and
> instances.
>
>I don't agree with this; it would be a real pain in the neck, and
>overkill, to have to define a whole new metaclass just to say how an
>instance is printed. Defining a method is far easier.
Yow! Ok, let's forget it then. The default PRINT-OBJECT can print
out in a nonreadable form, and it's up to the user to take care
of printing in a class or metaclass specific way.
From Gregor:
>Here is a related question?
>
>What happens if an object appears as a constant in a piece of code that
>is being compiled to a file? CLtL certainly is not clear on what
>happens if a defstruct-defined structure appears in such a place. Is
>print-object what you would like to call here??
In fact, CLtL doesn't specify how a constant ANYTHING gets compiled into
file. It doesn't even specify that two references to a constant
which are EQ during compilation will be EQ after the compiled file
is loaded. The only thing which my reading of CLtL seems to indicate
will be EQ is an interned symbol, and then only if the package exists
in the load environment.
I don't think you can realistically expect PRINT-OBJECT to be of use
here, since everyone will have a different low level representation
within compiled code files. The motivation for having a readable format
was for easy exchange of objects between machines, and the ability
to store objects in some default format, like DEFSTRUCT. But, as was
pointed out, a general solution is probably still a research question.
For examining the internals of an object, DESCRIBE (87-002, pg. 2-37)
or INSPECT (CLtL, pg. 442, but not in 87-002) could be used.
Jim Kempf kempf@hplabs.hp.com
∂15-May-87 1110 Gregor.pa@Xerox.COM optimization versus constructors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 May 87 11:10:32 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 MAY 87 11:07:52 PDT
Date: 15 May 87 11:07 PDT
From: Gregor.pa@Xerox.COM
Subject: optimization versus constructors
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870515-110752-4939@Xerox>
Danny and I have been thinking about initialization and are picking away
at parts of the problem we don't understand. Specifically, I was trying
to remember what the :constructor option was really for. I remembered
that:
- it isn't really just an abbreviation for a defun and a call to
make-instance since it can set slots which are not settable by initargs.
- even if it was just an abbreviation for a defun with a call to
make-instance, the constructors generated by the :constructor option
would be much faster than the ones defined by calling make-instance by
hand.
This message addresses the second of these 2 points. Specifically, I
will show a simple (even trivial) technique which reduces optimizing
calls to make-instance to exactly the same problem as optimizing
constructors produced by :constructor option. This is important because
it means that we can think about constructors only in terms of their
behavior, they are not needed for performance anymore.
The basic idea is that a call to make-instance with a constant first
argument and constant key (even numbered) args can be treated as a
dynamic definition of an :constructor with some gensymed name.
So that in the form
(progn .. (make-instance 'boat :speed 10) ..)
the call to make-instance can be converted to something like:
(progn .. (#:G001 10) ..)
and the class gets updated as if it had had a :constructor option
(:constructor #:g001 (speed)).
This shows that whatever optimization can be gotten from the
:constructor option can also be gotten from calls to make-instance (at
least the calls to make-instance for which you could have used a
constructor).
∂15-May-87 1240 kempf%hplabsc@hplabs.HP.COM Why is MAKE-INSTANCE not generic?
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 May 87 12:40:34 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 15 May 87 12:39:40 pdt
Received: by hplabsc ; Fri, 15 May 87 12:39:32 pdt
Date: Fri, 15 May 87 12:39:32 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705151939.AA11025@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Why is MAKE-INSTANCE not generic?
87-002 says that MAKE-INSTANCE is a function, and not a generic
function. Why is this? In particular, a metaclass may want
to specialize MAKE-INSTANCE to a particular metaclass-dependent
instance creation procedure. The instance "creation" procedure
might not fit into the ALLOCATE-INSTANCE/INITIALIZE pattern
which MAKE-INSTANCE currently uses. I realize that instance
creation is, as yet, not completely specified, but wanted to
bring up the point anyway.
Jim Kempf kempf@hplabs.hp.com
∂15-May-87 1315 kempf%hplabsc@hplabs.HP.COM Re: Why in MAKE-INSTANCE not generic?
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 May 87 13:15:24 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 15 May 87 13:14:28 pdt
Received: by hplabsc ; Fri, 15 May 87 13:14:48 pdt
Date: Fri, 15 May 87 13:14:48 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705152014.AA11627@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Why in MAKE-INSTANCE not generic?
There seems to be a slight discrepency between 87-002 and 87-003 on
this point. 87-002, pg. 2-44 implies that MAKE-INSTANCE is a programmer
interface function, 87-003, pg. 3-7 implies that it is a method
which is part of the metaobject protocol.
Jim Kempf kempf@hplabs.hp.com
∂15-May-87 1648 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Why in MAKE-INSTANCE not generic?
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 15 May 87 16:48:43 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 141322; Fri 15-May-87 19:37:40 EDT
Date: Fri, 15 May 87 19:36 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Why in MAKE-INSTANCE not generic?
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8705152014.AA11627@hplabsc>
Message-ID: <870515193649.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 15 May 87 13:14:48 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
There seems to be a slight discrepency between 87-002 and 87-003 on
this point. 87-002, pg. 2-44 implies that MAKE-INSTANCE is a programmer
interface function, 87-003, pg. 3-7 implies that it is a method
which is part of the metaobject protocol.
As you may have noticed, the protocol for creating objects hasn't been
defined yet. Anything that's in the documents now can't be relied upon.
∂15-May-87 1715 Moon@STONY-BROOK.SCRC.Symbolics.COM optimization versus constructors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 15 May 87 17:15:05 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 141385; Fri 15-May-87 20:14:21 EDT
Date: Fri, 15 May 87 20:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: optimization versus constructors
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870515-110752-4939@Xerox>
Message-ID: <870515201336.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 15 May 87 11:07 PDT
From: Gregor.pa@Xerox.COM
Danny and I have been thinking about initialization and are picking away
at parts of the problem we don't understand. Specifically, I was trying
to remember what the :constructor option was really for.
....
This shows that whatever optimization can be gotten from the
:constructor option can also be gotten from calls to make-instance (at
least the calls to make-instance for which you could have used a
constructor).
I agree that the :constructor mechanism could be replaced by a complicated
mechanism involving compile time optimizations of recognized patterns of
constant arguments to make-instance, with some way to get around the fact
that constructors can initialize any slot but we don't want make-instance
to be able to do that. There is some trickiness required to make this
compile-time optimized code get recompiled whenever the class's structure
is changed.
I don't remember who put constructors in, but I assume the idea was that
the other way of doing it was too complicated. It's probably a good model
for thinking about the semantics and making sure that constructors and
make-instance behave consistently, but we probably don't want to require
implementations to work that way.
∂20-May-87 1934 Pavel.pa@Xerox.COM CLOS vs. subtypes of FLOAT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 May 87 19:34:14 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 20 MAY 87 18:52:30 PDT
Date: Wed, 20 May 87 18:52:23 PDT
From: Pavel.pa@Xerox.COM
Subject: CLOS vs. subtypes of FLOAT
To: Common-Lisp-Object-System@SAIL.Stanford.Edu
Cc: Pavel.pa@Xerox.COM
Message-ID: <870520-185230-2840@Xerox>
Here it is, finally, my proposal(s) for the treatment of the subtypes of
FLOAT for discrimination in CLOS.
The issue, to refresh folks' memories, is what to do with code like the
following:
(defmethod foo ((x single-float)) ...)
(defmethod foo ((x double-float)) ...)
There are three major questions:
1) Is this code legal at all? That is, is it okay to discriminate on
the subtypes of FLOAT?
2) What is the effect of such code in an implementation that does not
represent the two types differently (such as one that has only one
representation of floating-point numbers)? Is it legal in such
implementations?
3) Which of the symbols naming subtypes of FLOAT also name classes?
Can this vary from implementation to implementation?
I have come up with three different proposals to answer these questions.
I will first lay them out and then discuss their relative advantages and
disadvantages.
Proposal 1 "NONE":
It is illegal to discriminate on any of the subtypes of FLOAT. None
of them name classes at all, in any implementation.
Proposal 2 "SOME":
In a given implementation, exactly as many of the subtype-symbols
name classes as there are different representations of floating-point
numbers. The ones that name classes are derived from the list of
allowable representation-naming schemes given on pages 18-19 of CLtL:
-- If there is only one representation, then SINGLE-FLOAT names a
class.
-- If there are exactly two representations, then either SHORT-FLOAT
and SINGLE-FLOAT, or SINGLE-FLOAT and DOUBLE-FLOAT, name classes.
-- If there are exactly three representations, then either
SHORT-FLOAT and SINGLE-FLOAT and DOUBLE-FLOAT, or SINGLE-FLOAT
and DOUBLE-FLOAT and LONG-FLOAT, name classes.
-- If four representations exist, then all four symbols name classes.
The classes named by such symbols are all subclasses of FLOAT. Clearly,
those symbols that do not name classes cannot be used for
discrimination.
Proposal 3 "ALL":
All of the subtype-symbols name classes, and all of those classes are
subclasses of FLOAT. In some implementations, some of the classes named
by those symbols are "synonyms" for other classes, according to the
following scheme (again derived from pages 18-19 of CLtL):
-- If there is only one representation, then the classes named by
SHORT-FLOAT, DOUBLE-FLOAT and LONG-FLOAT are all synonyms for the
class named by SINGLE-FLOAT.
-- If there are exactly two representations, then either
- the classes named by DOUBLE-FLOAT and LONG-FLOAT are synonyms
for the class named by SINGLE-FLOAT, or
- the class named by SHORT-FLOAT is a synonym for the class named
by SINGLE-FLOAT and the class named by LONG-FLOAT is a synonym
for the class named by DOUBLE-FLOAT
-- If there are exactly three representations, then either
- the class named by LONG-FLOAT is a synonym for the class named
by DOUBLE-FLOAT, or
- the class named by SHORT-FLOAT is a synonym for the class named
by SINGLE-FLOAT
-- If there are four representations, then no classess are synonyms
of others.
If a class A is a synonym of another class B, then A and B are not EQ,
they have different names, and they may have different metaclasses. No
instances may exist of class A. Defining a method on a generic function
F that discriminates on A has the same general effect as defining one
that discriminates on B. However, if a method already exists on F that
discriminates on B or a different synonym of B (i.e., not A), then a
correctable error is signalled, allowing the user to choose which one of
the two methods will remain on F.
Under the NONE proposal, the pair of DEFMETHOD's above would be illegal
in all implementations.
Under the SOME proposal, the pair would be legal in those
implementations that had distinct representations called SINGLE-FLOAT
and DOUBLE-FLOAT. In other implementations, an "Unknown class name"
error would be signalled.
Under the ALL proposal, the pair would compile and evaluate quietly and
correctly in those implementations that had distinct representations
called SINGLE-FLOAT and DOUBLE-FLOAT. In other implementations, a
correctable error would be signalled upon encountering the second
DEFMETHOD and the user would have to choose between the two methods.
I have been convinced by conversations with a number of floating-point
users around here that algorithms exist that can go much more quickly if
they can be guaranteed a certain minimum amount of precision in the
numbers. These algorithms would have to make checks for certain
conditions only if less precision is available. While these programs
would have to be conditionalized (using #+/#-) for different
implementations to patch in the name of the sufficiently-precise
representation (since CLtL does not give a required bit count for each
representation), this isn't very hard to do and should be allowed.
One can also imagine users who wish to use the very same source code for
some floating-point-intensive computation in two methods, one for
SINGLE-FLOAT arguments and one for DOUBLE-FLOAT arguments. The idea
here is that the compiler could generate much better code given the
implicit declaration of the argument type. Each of the two copies might
perform much better than an undeclared version. This user would be
letting the object system make a single check upon entry to the generic
function before dispatching to the representation-specific version of
the code.
I am convinced by arguments like these that reasonable uses exist for
discrimination on subtypes of FLOAT. Thus, I believe that the NONE
proposal is a bad idea.
The SOME proposal is very easy to implement, but has the (perhaps only
aesthetic) flaw that the existence of classes for certain built-in types
would vary between implementations. I find this notion disturbing and
would prefer not to see it.
The ALL proposal solves this problem but introduces, for almost all
implementations, the extra mechanism implied by the synonym classes. It
may be that this could be very easily implemented, but Gregor would
probably know better. An alternative to synonym classes would be making
the name -> class mapping be many-to-one. Gregor claims that this
cannot be allowed, but I'm not sure that I understand why. Another way
to avoid synonyms is to make the classes that would be synonyms into
subclasses of the other class. This, on the other hand, has the problem
that methods defined on such classes would never be called, since no
instances of them can be created. It also establishes an asymmetric
subclass relation for pairs with a symmetric subtype relation.
This is getting pretty long for such a relatively minor issue. I'll
stop here and see if anyone can make any sense of this.
Pavel
∂21-May-87 1228 Pavel.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 May 87 12:27:47 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 21 MAY 87 12:20:51 PDT
Date: Thu, 21 May 87 12:20:50 PDT
From: Pavel.pa@Xerox.COM
Subject: Re: CLOS vs. subtypes of FLOAT
In-reply-to: "Masinter's message of 21 May 87 12:07 PDT"
To: Masinter.pa@Xerox.COM
Cc: Common-Lisp-Object-System@SAIL.Stanford.Edu
Message-ID: <870521-122051-1382@Xerox>
Date: 21 May 87 12:07 PDT
From: Masinter.pa
You omitted the possibility where all the classes
exist in all implementations, but that some of the
classes might be empty (have no instances) in some
implementations.
In putting together the proposals, I had two (unfortunately unstated) design criteria:
1) Discrimination on the subtypes of FLOAT should be allowed
2) Discriminations that cannot work in a given implementation
(due to collapsing together some of the subtypes) should signal
an error so that the user doesn't lose quietly.
Proposal NONE loses on the first criterion and your proposal violates the second.
Pavel
∂21-May-87 1227 Masinter.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 May 87 12:27:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 MAY 87 12:08:02 PDT
Date: 21 May 87 12:07 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: CLOS vs. subtypes of FLOAT
In-reply-to: Pavel.pa's message of Wed, 20 May 87 18:52:23 PDT
To: Pavel.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.Stanford.Edu
Message-ID: <870521-120802-1365@Xerox>
You omitted the possibility where all the classes exist in all
implementations, but that some of the classes might be empty (have no
instances) in some implementations.
∂21-May-87 1338 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: CLOS vs. subtypes of FLOAT
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 May 87 13:38:33 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 146801; Thu 21-May-87 16:37:36 EDT
Date: Thu, 21 May 87 16:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: CLOS vs. subtypes of FLOAT
To: Common-Lisp-Object-System@SAIL.Stanford.Edu
In-Reply-To: <870521-120802-1365@Xerox>
Message-ID: <870521163738.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 21 May 87 12:07 PDT
From: Masinter.pa@Xerox.COM
You omitted the possibility where all the classes exist in all
implementations, but that some of the classes might be empty (have no
instances) in some implementations.
Unfortunately this elegant-sounding choice can't be taken without
changing Common Lisp incompatibly. The problem is that Common Lisp
specifies (CLtL p.19) that in an implementation without short-floats,
(typep x 'short-float) does the same thing as (typep x 'single-float),
rather than always returning nil. We want to keep typep consistent
with class-instance relationships, to avoid giving Common Lisp too
subtly-incompatible type systems.
∂21-May-87 1909 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 May 87 19:08:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 MAY 87 18:22:41 PDT
Date: 21 May 87 18:22 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Apr 87 01:30 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870521-182241-1963@Xerox>
I have elided parts of your message which I am not going to comment on
directly.
Date: Mon, 27 Apr 87 01:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Complexity and simplicity are partly matters of taste, and
largely matters of point of view.
I think this notion of what complexity and simplicity are is very
important to this discussion so, despite the fact that this is a
potential tarpit, I will try to make some comments about this.
I try to take the point of view
of the majority of programmers, who are using the outer interfaces
of the system without necessarily understanding everything that's
going on inside. No matter how beautifully we explain it, most
programmers simply won't read beyond the point where they think
they know everything they need to know to get their immediate job
done.
I agree.
Now, it may be that we will decide that we would rather make
life more complicated for people writing initialization methods in
order to make the conceptual explanation shorter.
Another way of saying this is "it may be that we will decide that we
would rather make it syntactically more complicated for people writing
initialization methods in order to make the conceptual explanation of
the system simpler". Let me try to explain why I would say it that way.
Because I agree with you that people will not read any more of the
documentation than they think they can get away with, I think it is
important for people to be able to develop mental models of the system
which have significant predictive power. By predictive power I mean
(among other things) it should be possible for a user to figure out how
to do something they haven't done before based on what they already
know. This means I believe it is often more important for a user to be
able to figure out how to do something than it is for there to be some
concise abbreviation for doing this 'new trick'.
Thus I believe that an important measure of a system's simplicity is the
ease with which users can develop a model of the system which has this
kind of predictive power.
In the example of initialization methods, my esthetic says that it would
be better for someone to be able to figure out how to write
initialization methods based on what they already know about ordinary
methods (without having to read any additional documentation) than it
would be for there to be some concise syntax for defining initialization
methods.
Note that this biases 'ease' away from the expert programmer. For the
record, I acknowledge this and this is consistent with my belief that it
is very difficult for an expert programmer to design something which is
really easy to understand. Expert programmers tend to design things
which have lots of 'bells and whistles' which make things simpler for
the expert user, but more complicated for everyone else. I will cite as
examples the Interlisp-D and LispM systems.
One key point that I was trying to convey, and I think
partially succeeded, was the need for information hiding
(abstraction) in the arguments to make-instance and in relations
among the various initialization specifications attached to a class
and its superclasses.
I agree that this is important, and your message does a good job of
collecting a lot of the reasons why this abstraction is important.
Remote initarg defaulting is related to this and your message does a
good job of describing why that is important.
Another key point, which I don't think came through, was that
each initarg should be explicitly defined, and should be defined in
exactly one place. This is simply good modularity.
I am not sure I agree with this. In fact, there are places later in
your message where you seem to disagree with this for the same reasons I
do.
Specifically, its not entirely clear to me what it means to 'define an
initarg'. Defining an initarg can mean specifying that this is a legal
initarg for a class (and its subclasses), or it can mean specifying what
the implementation of the processing this initarg should be. This is
like the protocol/implementation distinction. It would certainly be
'clean' for some sense of clean to require that legal initargs for a
class be specified in on option, and then there be other independent
mechanisms for specifying the implementation of those initargs
(corresponding to your types 1-4). One might argue that this is
cumbersome, but its important to understand that it would be simpler in
some senses.
--- reference ---
For reference, I am including the part of your message of April 16th
which defines initarg types 1-4.
From: David A. Moon
Date: Thu, 16 Apr 87 00:22 EDT
1. :allow-other-keys serves its usual function, as in all
&key argument lists. It isn't possible to define
additional initargs for step 1.
2. Initargs that control storage allocation are defined
by defining an allocate-instance method that accepts
the initarg as an &key argument. For example, in
systems with areas :area is an initarg for step 2.
The standard does not require any initargs to exist
for step 2.
3. Initargs that fill slots are defined by the :initarg
slot-option.
4. Initargs for initialization methods are defined by
defining an initialize-instance method that accepts
the initarg as an &key argument.
--- reference ---
All this leads to the idea that initargs of types 2 and 4 (in
the nomenclature of my 16 Apr message) should be defined by
methods, since their meaning is implemented by methods. Similarly,
type 3 should be defined by slot-options, since their meaning is
entirely involved with slots. In Flavors, type 4 have the ugly
property that they have to be defined in two places, once in the
method that implements them and again in a defflavor form; it's
easy to get these two places out of sync. Hence the proposal to
use the lambda-list of a defmethod as the way to define these
initargs.
As I said above, 'defining' in this paragraph can have two meanings.
The part of 'defining' which implements the behavior of the initarg
should definitely be close to 'the place that behavior affects or
happens'. So, slot setting initargs should have their behavior defined
in slots, initargs handled by methods should be in methods etc.
Along with this, I tried to eliminate clunky syntax from
initialization methods, hence the elimination of &allow-other-keys
and the elimination of having to write :before all the time. If
this is too confusing, we could invent a new syntax that both
defines initargs and defines the method that implements them.
Clearly this is the weakest part of my proposal.
As I said in my comments on what constitutes simplicity, I don't
necessarily agree that minor improvements in syntax (like removing
&allow-other-keys) always make for improvements in simplicity.
We could obviously simplify things a lot by getting rid of the
:constructor option to defclass. I didn't put it in, at least not
this year. I do think it ought to remain, in spite of its inherent
complexity in any initialization proposal (previous ones I've seen
have glossed over this rather than solving it), because I believe
many users will find it quite useful.
I don't know whether I like constructors yet or not. In my message last
week I tried to show that I think constructors are deceptively confsuing
because they contain a hidden performance optimization. I also think
they are deceptively confusing because the rules for breaking the
lambda-list down into initargs and setf of slot-value(s) are
complicated. Because :constructors are just an abbreviation for a defun
with a make instance and some setf of slot-values, I have separated them
from the rest of initialization for the time being. I want to think
about putting them back once we understand the rest better.
Date: Wed, 22 Apr 87 13:42 PDT
From: Gregor.pa@Xerox.COM
The special method combination type for initialize
instance adds considerable conceptual overhead for very little
functional gain.
The goal was not functional gain, that is, the ability to
program something you couldn't program before, but rather syntactic
simplicity. Perhaps in the end we'll decide it's not worth it, but
I'd like us to keep considering the question a bit longer.
My description of simplicity at the beginning of this message shows why
I think this extra method-combination type is not a net gain.
Date: Wed, 22 Apr 87 17:28 PDT
From: Gregor.pa@Xerox.COM
The default-initargs defclass option serves two
purposes. It specifies all the initargs which can be passed to
make-instance of this class, and it specifies default values
for some of those initargs.
This is an important modularity mistake, in my opinion. By
combining these two things, which ought to be separate, you have
lost the ability for one class to specify a default value for an
initarg defined by another class. If specifying a default value
always defines an initarg, there is no way to check the consistency
of the set of initargs with default values specified against the
set of initargs actually defined. If there is a misspelling, the
default value will simply be discarded, since no method will
receive it and do something with it.
I agree with this reasoning. This is the reasoning I was making
reference to earlier in this message when I said that there were reasons
not to 'define' initargs in one place.
∂22-May-87 0627 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: CLOS vs. subtypes of FLOAT
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 22 May 87 06:27:38 PDT
Received: from relay2.cs.net by RELAY.CS.NET id af20247; 22 May 87 9:21 EDT
Received: from ti-csl by RELAY.CS.NET id aj07513; 22 May 87 9:16 EDT
Received: by tilde id AA13337; Fri, 22 May 87 08:10:19 CDT
Message-Id: <2757676277-14030516@Jenner>
Date: Fri, 22 May 87 08:11:17 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Pavel.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: CLOS vs. subtypes of FLOAT
In-Reply-To: Msg of Wed, 20 May 87 18:52:23 PDT from Pavel.pa@xerox.com
Date: Wed, 20 May 87 18:52:23 PDT
From: Pavel.pa@xerox.com
Subject: CLOS vs. subtypes of FLOAT
I agree with you that proposal 1(NONE) is not desirable. If we pick 1, then
the choice of making float subtypes classes will be left to each
implementation, creating confusion for users.
Proposal 2(SOME), while OK on one implementation, will portable
applications make hard to develop. Users will have to conditionalize
the whole definition of some methods and the name of the float
specializers for some others.
Proposal 3(ALL), makes life of the user easier, but confront us to a new
problem, do we want to introduce class-synonyms. If we are to adopt 3,
then I think that class-synonyms should be standardized for general use.
Pavel brushes up two ways to address class-synonyms:
A:
If a class A is a synonym of another class B, then A and B are not EQ,
they have different names, and they may have different metaclasses. No
instances may exist of class A. Defining a method on a generic function
F that discriminates on A has the same general effect as defining one
that discriminates on B. However, if a method already exists on F that
discriminates on B or a different synonym of B (i.e., not A), then a
correctable error is signalled, allowing the user to choose which one of
the two methods will remain on F.
B:
An alternative to synonym classes would be making the name -> class
mapping be many-to-one.
B: seems a lot simpler than A:. It does not affect class objects, just
the name space. It opens up some issues for class-redefinition though.
I don't like 3A:
Another way to avoid synonyms is to make the classes
that would be synonyms into subclasses of the other class. This, on the
other hand, has the problem that methods defined on such classes would
never be called, since no instances of them can be created. It also
establishes an asymmetric subclass relation for pairs with a symmetric
subtype relation.
Because it would break the subtypep-subclassp identity.
Patrick.
∂22-May-87 0725 DLW@ALDERAAN.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 22 May 87 07:25:35 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 84672; Fri 22-May-87 10:07:17 EDT
Date: Fri, 22 May 87 10:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: Re: Object creation discussion (at last!)
To: Gregor.pa@Xerox.COM, Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870521-182241-1963@Xerox>
Message-ID: <870522100649.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
Line-fold: No
Date: 21 May 87 18:22 PDT
From: Gregor.pa@Xerox.COM
From: Moon
Along with this, I tried to eliminate clunky syntax from
initialization methods, hence the elimination of &allow-other-keys
and the elimination of having to write :before all the time. If
this is too confusing, we could invent a new syntax that both
defines initargs and defines the method that implements them.
Clearly this is the weakest part of my proposal.
As I said in my comments on what constitutes simplicity, I don't
necessarily agree that minor improvements in syntax (like removing
&allow-other-keys) always make for improvements in simplicity.
This kind of thing is a real bear. I think you're both right. I've
been caught on the horns of this dilemma many times before. It's
frustrating, because I always feel that you're damned if you do and
damned if you don't. Either you have to put in special-case material
that increases conceptual complexity, or you have to make everybody put
up with a clumsy syntax. This seems to be one of those cases where it's
hard to avoid one evil or the other. I don't see any decision criterion
that's clearly overriding. If anyone has any new insights into this
generic problem, I'd love to hear them.
∂22-May-87 1002 kempf%hplabsc@hplabs.HP.COM Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 22 May 87 10:02:03 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 22 May 87 10:01:28 pdt
Received: by hplabsc ; Fri, 22 May 87 10:00:54 pdt
Date: Fri, 22 May 87 10:00:54 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705221700.AA01346@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Arguments to CALL-NEXT-METHOD
The ANSI 87-002 CLOS spec, pg. 2-6-2-7 states that rebinding of
argument parameters for CALL-NEXT-METHOD is not permitted, but
that a proposed extension is to allow it to accept arguments.
I would like to inquire about the reason for not allowing
parameter rebinding, and propose that, if no important arguments
against it are forthcoming, the proposed extension be accepted.
The reason is that, in the process of implementing COOL, I have
found need to do this.
Jim Kempf kempf@hplabs.hp.com
∂22-May-87 1116 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 May 87 11:16:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 MAY 87 11:04:43 PDT
Date: 22 May 87 11:04 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Fri,
22 May 87 10:00:54 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870522-110443-2785@Xerox>
The ANSI 87-002 CLOS spec, pg. 2-6-2-7 states that rebinding of
argument parameters for CALL-NEXT-METHOD is not permitted,
Actually, what it says is:
"Neither argument defaulting, nor using setq, nor rebinding variables
with the same
names as parameters of the method affects the values call-next-method
passes to the
method it calls."
By which it means the following is legal:
(defmethod foo ((b boat) x y)
(let ((x (1+ x))
(y (1+ y)))
(call-next-method)))
But that the next method will be called with the original values of x
and y, not one plus those values.
The reason is that, in the process of implementing COOL, I have
found need to do this.
Having made the clarification above, I would ask: Have you found the
need to rebind the parameters of the method or alter the values passed
by call-next-method? I would guess the latter since that is whats
really interesting and the only thing you couldn't get around by
renaming variables.
We should probably work this out so that it is possible to pass
arguments to call-next-method. As I remember, the problems were
specifying what happens if you change the arguments passed in such a way
that the current method itself would no longer be applicable.
∂22-May-87 1635 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 May 87 16:35:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 MAY 87 16:10:34 PDT
Date: 22 May 87 16:10 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Apr 87 01:30 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870522-161034-1060@Xerox>
This message talks only about the things that I think happen with
initargs in Moon's proposal. Most of what I am going to say is just a
re-interpretation of Moon's description of his proposal. In Moon's
proposal there are lots of different declarations which involve
initargs, I am trying to understand just what those declarations really
say.
It seems to me that there are 3 different kinds of primitive
declarations involving initargs.
1) DECLARATION of Legality
This is a statement that in a call to make-instance of this class
or a subclass of this class it is legal to provide this initarg.
This primitive declaration does not exist in isolation in in Moon's
proposal, more on that later.
2) SPECIFICATION of how to process certain kinds of initargs.
This is a statement telling the system how to process a particular
initarg. In Moon's proposal, initargs which set slots are one
example of SPECIFICATION. Using the :initarg slot-option tells the
system that when that initarg is supplied the associated slot
should be set to the initargs value.
Another, more subtle, example of SPECIFICATION is the &key keywords
in initialize-instance method lambda-lists. These specify that a
given parameter in the method body should be bound to the value of
the initarg.
3) DEFAULTING the value of an initarg.
This provides a default value for an initarg be it an initarg which
is DECLARED in this class or one which is DECLARED in a superclass
of this class.
Moon's proposal tends to fold one or more of these primtive declarations
together in other declarations. That is probably appropriate, and I
would expect that our final design will do so as well. I am making
these distinctions now so that we can have some more precise mechanism
for talking about the kinds of things that can be done with initargs.
In Moon's proposal:
:initarg slot-options combines DECLARATION and SPECIFICATION
&key in initialize-instance combines DECLARATION and SPECIFICATION
:default-initargs combines DECLARATION (and DEFAULTING I
think)
Now lets look for a minute at how initargs are processed at
make-instance time. This breakdown also helps justify the breakdown I
used above.
Note that this is a naive model of how they are processed. Any
implementation would optimize this.
1. defaulting
the initargs supplied in the call to make-instance are combined
with the inherited initarg default values to get the full set of initargs.
2. declaration checking (error checking)
the full set of initargs is error checked to make sure they are all
legal
3a. specification implementation for slot initargs
the initargs which specify slot values are used to set slot values,
(slots not set in this way are set from their initforms)
3b. specification implementation for other initargs
call initialize-instance with the instance and the initargs.
Let me re-iterate the point of this message. I am just trying to flesh
out the primitive language of statements about initargs which I think
underlies Moon's proposal. I am not necessarily suggesting that this
primitive language is appropriate for use in the system, it may be that
we will want to continue using combined declarations. But I think this
language can be used to describe Moon's proposal, my earlier proposal
and one that Danny has been working on. As such I think it might be
helpful to us in trying to talk about these proposals.
∂23-May-87 0414 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 23 May 87 04:13:58 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Fri, 22 May 87 14:22:05 pdt
Received: by hplabsc ; Fri, 22 May 87 14:18:53 pdt
Date: Fri, 22 May 87 14:18:53 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705222118.AA05249@hplabsc>
To: Gregor.pa@Xerox.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
Cc: common-lisp-object-system@sail.stanford.edu
The problem required altering the values passed by CALL-NEXT-METHOD.
Passing arguments which would make the current method not be applicable
is certainly a problem which would need some thought. Off the top
of my head, two solutions I could think of would be to only allow
parameters to be passed which are not specialized in the lambda
list of the method or simply signal an error if no method exists.
I don't think there is any way to make this work with method combination
either, since the :AROUND method depends on CALL-NEXT-METHOD, according
to 87-001, pg. 1-24.
Jim Kempf kempf@hplabs.hp.com
∂23-May-87 1622 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 May 87 16:22:40 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 MAY 87 16:22:03 PDT
Date: 23 May 87 16:21 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Fri,
22 May 87 14:18:53 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: Gregor.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870523-162203-1587@Xerox>
Passing arguments which would make the current method not be
applicable is certainly a problem which would need some thought.
Off the top of my head, two solutions I could think of would be to
only allow parameters to be passed which are not specialized in the
lambda list of the method or simply signal an error if no method
exists.
The model I prefer is that call-next-method arguments that are used for
method discrimination must have the SAME class as the supplied value.
This should be checked at run-time and an error signalled if not true.
If the compiler can PROVE that the new parameter will have the same
class then as an optimization the check may be skipped. Thus changing
some arguments, but passing down the input parameters which are not
special and have not been rebound fall in that category.
Of course, undiscriminated arguments can be changed freely.
∂23-May-87 1839 Bobrow.pa@Xerox.COM Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 May 87 18:39:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 MAY 87 18:35:30 PDT
Date: 23 May 87 18:35 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Object creation discussion (at last!)
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870523-183530-1635@Xerox>
The following is another proposal for instance allocation. Consider it
as a thought exercise to try to understand what might be possible. It
tries to provide the same functional capabilities as Moon's, but takes a
different point of view with respect to simplicity -- by trying to
adding the smallest number of new features . The messages by Moon and
Gregor have been most clarifying on these diffeent views of simplicity.
This proposal builds both their previous proposals, but is more in the
spirit of Gregor's. After the specification, I respond to issues that
have come up in previous messages.
The proposal
1) provides a specializable, error-checkable intermodule mechanism for
creating instances (make-instance).
2) divides the instance creation specification between internal and
interface parts (:initargs option). The external part specifies
allowable arguments to make-instance.
3) assumes optimization of specific calls to make-instance with quoted
arguments so that creating instances can be fast (see Gregor's recent
message), thus allowing removal of the :constructor option.
----
PROPOSAL:
The defclass class options no longer include a :constructor option.
The defclass class options are extended to include:
(:initargs (<initarg-name>
[:slotname <slot-specifier>]
[:default-value-form <form>])*)
Each <initarg-name> is a symbol specified to be a legal argument to
make-instance.
<initarg-name> is an abbreviation for (<initarg-name>).
:slotname <slot-specifier>
<slot-specifier> is <symbol> or (<symbol>*)
If <initarg-name> is used as a keyword argument to make-instance, then
the slot named <symbol> is initialized to the value provided for the
<initarg-name> argument. If <slot-specifier> is a list of <symbol>s,
then all those named slots are initialized with the same provided value.
An error is signalled for any <symbol> that does not name a slot of the
class.
:default-value-form <form>
If :default-value-form is provided, and if <initarg-name> is not
supplied explicitly in the call to make-instance, then the value of
<form> is used by make-instance as though it were provided. The
:default-value-form is evaluated in the lexical context of the defclass
form.
In the following, we say that an <initarg-name> has a "provided value"
if either
1) it is provided in the call to make-instance
2) the <initarg-name> has a :default-value-form
Multiple occurrences of <initarg-name>
If the same <initarg-name> appears more than once in the :initargs list,
it is equivalent to a single appearance of this symbol with the union of
the values of all the :slotname options, and the first (leftmost)
:default-value-form option.
Inheritance
The effective :initargs list for any class is the concatenation of lists
from all of the classes in its class-precedence-list in that order (most
to least specific). The multiple occurrence rule defines the behavior
for multiple occurrences of <initarg-name>.
Multiple occurrences of <slotname>
If more than one <initarg-name> is specified to initialize a particular
slot, then all of them CAN be used to initialize the slot. The leftmost
provided value (leftmost in the effective :initargs list) will be used
to initialize the slot.
Interaction with slot initforms
If an <initarg-name> has a provided value, then that provided value is
used to initialize the slot, else it is initialized as specified in the
slot :initform option.
EXAMPLES:
(defclass point ()
((x :initform 0)
(y :initform 0))
(:init-args
(:x :slotname x)
(:y :slotname y)
:rho
:theta)
The keywords :x, :y, :rho and :theta are legal arguments to
make-instance. Values provided for :x and :y initialize slots x and y
respectively. If there are no provided values, x and y are initialized
to 0.
(defclass picture (point)
(bitmap
saved-bitmap)
(:init-args
(:y :default-value-form *screen-top*)
(:image :slotname (bitmap saved-bitmap))))
:x, :y, :rho, :theta, and :image are legal arguments to make-instance. A
value provided for :image will initialize both slots bitmap and
saved-bitmap. If a call to make-instance does not specify a value for
:y, then the slot y will be initialized to *screen-top*, and
initialize-instance will see a provided value of *screen-top* for :y.
GENERIC FUNCTION INVOLVED IN OBJECT CREATION
MAKE-INSTANCE kind &rest init-plist
is a generic function that provides the external interface to object
creation. Methods exist for symbol and standard-class.
Method on SYMBOL
It finds the class of that name, and calls the generic-function on the
class. It signals an error if no such class is found.
Method on STANDARD-CLASS
This method checks the init-plist. It ensures that init-plist contains
only <initarg-name>s that are allowed by the class, else signals an
error. For each <initarg-name> that has a <default-value-form>, and
does not appear in the init-plist, it appends <initarg-name>
<value-of-form> to init-plist.
This method then calls allocate-instance with the class, and the
extended init-plist.
On the object returned from allocate-instance, this method first
initializes all slots that have an associated <initarg-name> and a
provided value, and then initializes the rest of the slots from their
slot-option :initform.
This method then calls initialize-instance on the object, and the
extended init-plist.
ALLOCATE-INSTANCE class &key &allow-other-keys.
returns a new uninitialized instance of the specified class.
INITIALIZE-INSTANCE instance &key &allow-other-keys
is the user's procedural handle on initialization. It uses
standard-method-combination. The primary method on standard-object just
returns the instance. One standard way of using initialize will be to
have :before methods, so that all these methods will be fired.
CLASS-INITARGS class &optional local-only
returns the initargs for a standard-class. setf works with
class-initargs when local-only is T.
----
ISSUES raised in messages:
1) Lexical proximity (ie why not have an :initarg slot option)
The criterion for simplicity used here is that there should be
exactly one way of specifying legal initargs-names. This simplifies
code for readers who minimize reading of documentation. Another
argument is that specifying initargs is part of the interface, not the
implementation, and hence does not belong with the slot.
I also believe that it is the environment's responsibility to provide
useful views of the class in addition to the text view in the file; for
example, allowing one to see the set of all slots in a class and all
their effective slot-options. Another such view should show the names
of initarg-names that can be used to initialize particular slots.
2) Can methods specify legal :initargs not in the class :initargs
option?
No, because the specification is part of the class definition. The
method is an implementation of part of the specification.
3) How should methods and initargs be kept in synch
Again I believe this is something that a good environment will help
with. No later than the time when the first instance is created, the
environment can warn the user about :initarg-names that are not used for
methods or slot initialization, and methods with illegal argument names.
4) Why get rid of constructors?
This again calls on the simplicity criterion of having only one way
to do something. Also, I found the rules for matching constructor
argument names with slotnames and initarg-names were very complicated
and confusing.
The two arguments for constructors were:
1) Optimized code can be written for the constructors. But Gregor
showed how this can be done for an equivalent set of calls to
make-instance with quoted arguments. These calls can even be compiled
in-line if desirable.
2) Constructors can initialize slots that have no external interface.
But so can user functions that call make-instance.
5) Why keep :initforms?
Gregor has suggested that we eliminate the slot :initform option. I
have not suggested this because I believe that :initforms are part of
the internal specification of the class, and :default-value-form is part
of the external specification.
6) Why is make-instance a generic function?
This allows the user to specialize make-instance for different
meta-classes, thus avoiding any of the initialization protocol. I could
also imagine using it for objects that I want to create only if I
couldn't find an existing object with the a given unique-identifier.
The only argument I remember against make-instance as a generic function
was that constructors didn't call make-instance, so it was the wrong
level to have a generic function. I take this to be an argument against
having constructors.
7) What about a more compact syntax?
Since there are only two options for an initarg-name, we could use
positional notation, with
(<initarg-name> <slot-specifier> <default-value-form>).
We could then use
(<initarg-name> <slot-specifier>)
if no <default-value-form> is to be given, and
(<initarg-name> NIL <default-value-form>)
if no <slot-specifier> is to be given, and
<initarg-name>
for no options.
8) Must the user specify &allow-other-keys and :before for
initialize-instance?
A simple macro can add the first or both of these.
I believe that this is another example where the standard should be
augmented by a STANDARD library of useful extensions endorsed by the
committee. Other things in that category for me are the macro for
defining simple-method-combination, and the standard simple
method-combination forms (and, or etc.). This is a fourth layer for the
standard.
∂25-May-87 0816 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 25 May 87 08:16:14 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Mon, 25 May 87 08:15:08 pdt
Received: by hplabsc ; Mon, 25 May 87 08:14:20 pdt
Date: Mon, 25 May 87 08:14:20 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705251514.AA22567@hplabsc>
To: Bobrow.pa@Xerox.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
Cc: Gregor.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
>The model I prefer is that call-next-method arguments that are used for
>method discrimination must have the SAME class as the supplied value.
>This should be checked at run-time and an error signalled if not true.
>If the compiler can PROVE that the new parameter will have the same
>class then as an optimization the check may be skipped. Thus changing
>some arguments, but passing down the input parameters which are not
>special and have not been rebound fall in that category.
This would also be acceptable, and would provide even more flexibility,
since the writer of the subclass method would have the option of
passing another object of the same class as one of the specialized
arguments. The capability to alter arguments is typically required
when the writer of the subclass method wants to filter the arguments
before passing them to the superclass method.
Jim Kempf kempf@hplabs.hp.com
∂25-May-87 1754 masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 May 87 17:54:10 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 25 MAY 87 17:52:57 PDT
From: masinter.pa@Xerox.COM
Date: 25 May 87 17:52:36 PDT
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: kempf%hplabsc@hplabs.HP.COM's message of Mon, 25 May 87
08:14:20 pdt, <8705251514.AA22567@hplabsc>
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM,
common-lisp-object-system@sail.stanford.edu
Message-ID: <870525-175257-2213@Xerox>
Does 3 have the same class as 3333333?
∂25-May-87 1818 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 25 May 87 18:18:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 25 MAY 87 18:15:42 PDT
Date: 25 May 87 18:15 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: masinter.pa's message of 25-May-87 17:52:36 PDT
To: masinter.pa@Xerox.COM
cc: kempf%hplabsc@hplabs.HP.COM, Bobrow.pa@Xerox.COM,
Gregor.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870525-181542-2236@Xerox>
Does 3 have the same class as 3333333?
Yes. Subranges do not have classes. (e.g. fixnums)
danny
∂26-May-87 1724 Masinter.pa@Xerox.COM Re: CLOS vs. subtypes of FLOAT
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 May 87 17:24:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 26 MAY 87 15:56:56 PDT
Date: 26 May 87 15:47 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: CLOS vs. subtypes of FLOAT
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 21 May 87 16:37 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.Stanford.Edu
Message-ID: <870526-155656-1011@Xerox>
>From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: CLOS vs. subtypes of FLOAT
...
>Unfortunately this elegant-sounding choice can't be taken without
>changing Common Lisp incompatibly. The problem is that Common Lisp
>specifies (CLtL p.19) that in an implementation without short-floats,
>(typep x 'short-float) does the same thing as (typep x 'single-float),
>rather than always returning nil. We want to keep typep consistent
>with class-instance relationships, to avoid giving Common Lisp too
>subtly-incompatible type systems.
The conclusion I've reached is that there is no good way to allow
discrimination on subtypes of FLOAT without changing Common Lisp, or at
least the required subtypes of FLOAT.
I'd vote for adopting Pavel's proposal NONE with the footnote that a
cleanup in the area of floating point classes is required., because the
current floating point types are not sufficiently well specified to
allow any useful discrimination on them.
∂26-May-87 2253 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 May 87 22:53:13 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 152832; Wed 27-May-87 01:52:38 EDT
Date: Wed, 27 May 87 01:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <870523-162203-1587@Xerox>
Message-ID: <870527015250.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 May 87 16:21 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Passing arguments which would make the current method not be
applicable is certainly a problem which would need some thought.
The model I prefer is that call-next-method arguments that are used for
method discrimination must have the SAME class as the supplied value.
This should be checked at run-time and an error signalled if not true.
If the compiler can PROVE that the new parameter will have the same
class then as an optimization the check may be skipped. Thus changing
some arguments, but passing down the input parameters which are not
special and have not been rebound fall in that category.
Of course, undiscriminated arguments can be changed freely.
This sounds good. There are two problems I remember from the last time
we discussed this. One is that testing the class isn't good enough since
we have method selection by eql as well as by typep. I guess all this
means is that the -only- way the compiler can prove that the run-time
test isn't needed is when you pass exactly the input parameter; but that
is the important special case.
The other problem is that the issue is not passing arguments which would
make the -current- method not be applicable, so much as passing
arguments which would change which -other- methods are applicable. This
is particularly easy to see in an implementation model where the generic
function first finds all the applicable methods and sets them up for
call-next-method, and then calls the first method, and call-next-method
just pulls methods off that list. Because of this problem, you can't do
anything at compile time because you don't know which parameters of the
generic function are used for method selection; they might be more than
just the specialized parameters of the current method. They might change
long after the current method is compiled, by defining a new method
that specializes a different parameter.
Does anyone think we couldn't get away with this rule, which I think is
the most restrictive possible, short of not being able to change the
arguments at all (as in 87-002): Call a parameter of the generic
function "discriminating" if -any- method for that generic function
specializes the parameter. Each argument to call-next-method that
corresponds to a discriminating parameter of the generic function must
be EQL to the argument supplied to the generic function or an error is
signalled. The other arguments to call-next-method can be changed
freely. Optimizations of the error checking are possible but they
should be invisible to the programmer.
Less restrictive rules are possible but all I could think of
either were much more complicated to explain, or admitted bugs, or both.
∂26-May-87 2259 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 May 87 22:59:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 152858; Wed 27-May-87 01:59:04 EDT
Date: Wed, 27 May 87 01:59 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Object creation discussion (at last!)
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870522-161034-1060@Xerox>
Message-ID: <870527015917.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 22 May 87 16:10 PDT
From: Gregor.pa@Xerox.COM
This message talks only about the things that I think happen with
initargs in Moon's proposal. Most of what I am going to say is just a
re-interpretation of Moon's description of his proposal. In Moon's
proposal there are lots of different declarations which involve
initargs, I am trying to understand just what those declarations really
say.
It seems to me that there are 3 different kinds of primitive
declarations involving initargs.
1) DECLARATION of Legality
This is a statement that in a call to make-instance of this class
or a subclass of this class it is legal to provide this initarg.
This primitive declaration does not exist in isolation in in Moon's
proposal, more on that later.
2) SPECIFICATION of how to process certain kinds of initargs.
This is a statement telling the system how to process a particular
initarg. In Moon's proposal, initargs which set slots are one
example of SPECIFICATION. Using the :initarg slot-option tells the
system that when that initarg is supplied the associated slot
should be set to the initargs value.
Another, more subtle, example of SPECIFICATION is the &key keywords
in initialize-instance method lambda-lists. These specify that a
given parameter in the method body should be bound to the value of
the initarg.
3) DEFAULTING the value of an initarg.
This provides a default value for an initarg be it an initarg which
is DECLARED in this class or one which is DECLARED in a superclass
of this class.
I agree with this analysis.
Moon's proposal tends to fold one or more of these primtive declarations
together in other declarations.
Forbidding DECLARATION independently of SPECIFICATION was intended to be
a FEATURE of what I proposed. That is, the specifications and the
declarations were supposed to be kept consistent automatically by not
having a syntax that could make them inconsistent.
That is probably appropriate, and I
would expect that our final design will do so as well. I am making
these distinctions now so that we can have some more precise mechanism
for talking about the kinds of things that can be done with initargs.
I agree that this is a good way to proceed.
In Moon's proposal:
:initarg slot-options combines DECLARATION and SPECIFICATION
&key in initialize-instance combines DECLARATION and SPECIFICATION
Agreed.
:default-initargs combines DECLARATION (and DEFAULTING I
think)
No, that's a persistent misunderstanding (my "at last" writeup was not
very clear on this). :default-initargs does DEFAULTING only.
Now lets look for a minute at how initargs are processed at
make-instance time. This breakdown also helps justify the breakdown I
used above.
Note that this is a naive model of how they are processed. Any
implementation would optimize this.
1. defaulting
the initargs supplied in the call to make-instance are combined
with the
inherited initarg default values to get the full set of initargs.
2. declaration checking (error checking)
the full set of initargs is error checked to make sure they are all
legal
3a. specification implementation for slot initargs
the initargs which specify slot values are used to set slot values,
(slots not set in this way are set from their initforms)
3b. specification implementation for other initargs
call initialize-instance with the instance and the initargs.
I agree with this.
Let me re-iterate the point of this message. I am just trying to flesh
out the primitive language of statements about initargs which I think
underlies Moon's proposal. I am not necessarily suggesting that this
primitive language is appropriate for use in the system, it may be that
we will want to continue using combined declarations. But I think this
language can be used to describe Moon's proposal, my earlier proposal
and one that Danny has been working on. As such I think it might be
helpful to us in trying to talk about these proposals.
Thanks, this is a good framework for focussing the discussion.
∂26-May-87 2335 kempf%hplabsc@hplabs.HP.COM Re: CLOS vs. subtypes of FLOAT
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 26 May 87 23:35:06 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 26 May 87 21:00:10 pdt
Received: by hplabsc ; Tue, 26 May 87 20:59:25 pdt
Date: Tue, 26 May 87 20:59:25 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705270359.AA00431@hplabsc>
To: Masinter.pa@Xerox.COM, Moon@STONY-BROOK.SCRC.Symbolics.COM
Subject: Re: CLOS vs. subtypes of FLOAT
Cc: Common-Lisp-Object-System@SAIL.Stanford.Edu
I agree on adopting the NONE proposal, with cleanup on float subtyping.
∂27-May-87 0803 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 08:03:04 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 08:00:39 PDT
Date: 27 May 87 08:00 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 27 May 87 01:52 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-080039-1739@Xerox>
Call a parameter of the generic function "discriminating" if
-any- method for that generic function specializes the parameter.
Each argument to call-next-method that corresponds to a
discriminating parameter of the generic function must be EQL to the
argument supplied to the generic function or an error is signalled.
The other arguments to call-next-method can be changed freely.
Optimizations of the error checking are possible but they should be
invisible to the programmer.
You are correct that we must consider all arguments that could be
discriminating.
The appropriate rule is
*The set of methods applicable to a changed set of arguments for
call-next-method must be the same as set of applicable methods for the
original arguments to the method". There are various compilations of
this rule.
Call any parameter of the generic function that is discriminated on an
individual an "individual discriminated parameter" and the others "class
discriminated parameters". Then the rule is that one cannot change the
class (even the implementation dependent class) of a class discriminated
argument, nor the identity (EQL) of an individual discriminated
argument.
Here is an example where one wants to change the value of a class
discriminated parameter. A gauge is a display device. Assume
different behaviors for integers and floating point input to the gauge.
(defmethod display-value ((g gauge)(i integer))
(move-display-to-position g i)) ;; show value whatever
it is
(defclass bounded-gauge (gauge)
((max-reading :initform 100)))
(defmethod display-value ((g bounded-gauge) (i integer))
(with-slots (g)
(call-next-method g (min i max-reading))))
∂27-May-87 1057 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 May 87 10:56:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 153591; Wed 27-May-87 13:49:35 EDT
Date: Wed, 27 May 87 13:49 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <870527-080039-1739@Xerox>
Message-ID: <870527134949.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 May 87 08:00 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The appropriate rule is
The set of methods applicable to a changed set of arguments for
call-next-method must be the same as the set of applicable methods for the
original arguments to the method".
Okay, I'll buy that.
Here is an example where one wants to change the value of a class
discriminated parameter. A gauge is a display device....
It's a somewhat contrived example, but I get your point.
Shall we call this a decision and record it someplace?
∂27-May-87 1122 RPG OOPSLA Lisp and Object-Oriented Programming Workshop
To: common-lisp-object-system@SAIL.STANFORD.EDU
There will be a workshop on Lisp and Object-Oriented Programming on Monday
October 5 from 9am until noon at OOPSLA. The Common Lisp Object System
(CLOS) will be the highlight of the workshop, with presentations about
CLOS by the designers along with critiques, analyses, and responses to the
Object System, the latter selected based on contributed position papers.
Attendance will be limited to people who know Lisp and are familiar with
existing object-oriented languages.
If you would like to attend, please send me a 1-2 page description of your
position regarding either the Common Lisp Object System or
Lisp/object-oriented programming before August 1; netmail is acceptable.
Invitations will be sent on September 1. Attendance is limited to 35
people.
Richard P. Gabriel
Lucid, Inc
707 Laurel Street
Menlo Park, CA 94025
(415)329-8400
rpg@sail.stanford.edu
∂27-May-87 1124 RPG Floats
To: common-lisp-object-system@SAIL.STANFORD.EDU
Pavel's note provides a good analysis, but we should take it further. I
think there are a number of issues at work here: 1. Common Lisp makes it
difficult or impossible to put forward a sensible definition of the class
structure of floats even when only one implementation is considered; 2. a
class structure that parallels the type structure of floats is not useful
to solve the problem of portability of CLOS code among implementations; 3.
CLOS does not provide the sort of expressive machinery to solve these
problems even if we drop the requirement of making the class structure
parallel the type structure.
Let us suppose that if a programmer writes
(defmethod foo ((x single-float))...)
(defmethod foo ((x double-float))...)
he intends that the first method will be used when the internal
representation of the argument to FOO has some limited precision and that
the second method will be used when there is more precision. As Pavel
points out, different programs or even algorithms will be used depending
on the precision of floats available. I will ignore the case that the
programmer is trying to tell the compiler how to improve the code.
In addition, the programmer is providing additional documentation
of his code by defining the methods like this - the reader knows
that the two methods are carefully chosen to behave well for certain
precisions of floating point.
Issue 1:
I will present a scenario for a valid (and sensible) Lisp implementation
situation in which the implied class structure tends to be nonsensical
because the Common Lisp type system is slightly nonsensical.
Today, there are computers that have only double-precision floating point
hardware. These vendors often support languages in which variables can be
declared of type SINGLE-FLOAT (in effect), but these languages produce
code that loads the floating point hardware with the values of such
variables by coercing to doubles, operates on them, and then unloads
to the variables, coercing to SINGLE-FLOATs on the way. People who have
code that is already declared with SINGLE-FLOATs are happy to suffer only
a 10%-20% slowdown over what they would get if they changed their code to
declare DOUBLE-FLOATs.
A Common Lisp for this machine, then, might use only a double-precision
representation throughout. But, according to pages 18-19 of CLtL, this
type would be considered SINGLE-FLOAT, though the types SHORT-FLOAT,
DOUBLE-FLOAT, and LONG-FLOAT are synonymous with it as far as TYPEP is
concerned. FORMAT will consider all floating point numbers to be singles
and output accordingly.
The result is that the programmer who writes FOO as above would not have
an implementation that distinguishes between SINGLE-FLOAT and
DOUBLE-FLOAT. In his implementation, there is only one floating point
representation, and to write a method that invokes the double-precision
code he could write the single method as one of:
1. (defmethod foo ((x float))...)
2. (defmethod foo ((x single-float))...)
3. (defmethod foo ((x double-float))...)
The first and second of these are possibilities under Pavel's SOME
proposal, while the third is a possibility under Pavel's ALL proposal.
The first of these would work because there is only one subclass of FLOAT,
namely SINGLE-FLOAT, and therefore FLOAT and SINGLE-FLOAT are synonymous.
The second of these works because double-precision numbers are of class
(and type) SINGLE-FLOAT. The third of these works if CLASS-OF is allowed
to return DOUBLE-FLOAT or if the class SINGLE-FLOAT is a subclass of
DOUBLE-FLOAT. CLtL doesn't state what TYPE-OF should return, but it seems
to make sense for it to return SINGLE-FLOAT to help FORMAT do its thing.
The first of these alternatives fails to provide the best documentation,
because it seems to be a method defined for a general class of floats,
from SHORT-FLOATs to LONG-FLOATs. The second one is misleading. The third
of these alternatives possibly forces us into an inconsistency with the
Common Lisp type structure.
None of these alternatives is satisfying. This argues that CLtL
incorrectly outlines the acceptable type structures for floats.
Basing a rational class structure on an irrational type structure
seems inadvisable.
Issue 2:
Suppose we have two Common Lisp implementations, each with all of the
possible subtypes of FLOAT as distinct types with distinct representations.
Suppose further that the first implementation is on an S3 where a
SHORT-FLOAT is an immediate type with 32 bits of mantissa, a SINGLE-FLOAT
is a boxed type with 64 bits of mantissa, a DOUBLE-FLOAT is a boxed type
with 128 bits of mantissa, and a LONG-FLOAT is a boxed type with
256 bits of mantissa.
Suppose the second implementation is on a 68020 with special floating-point
hardware where a SHORT-FLOAT is an immediate type with 22 bits of mantissa,
SINGLE-FLOATs are boxed with 28 bits of mantissa, DOUBLE-FLOATs are boxed
with 56 bits of mantissa, and LONG-FLOATS are boxed with 80 bits of mantissa.
Now suppose that the programmer for the second machine has 4 methods,
one for each type of float where each method performs a different
computation based on the convergence properties of each floating point
type. When he tries to port his code to the first machine, the methods
get mapped to the four classes, but his programs are wrong! His SHORT-FLOAT
method is obsolete, the next three shift down one, and he has to think about
a LONG-FLOAT version for the expanded precision.
That is, the names of the types match, but the underlying descriptions of
of the representations do not.
The point is that the proposal to parallel the Common Lisp type structure
with a class structure is based on the belief that programmers want to tailor
code to the floating point formats available on a machine, but the fact
is that programmers who write such code wish to have their methods chosen
on the basis of a description of the floating point precisions and not on some
set of names of floating point types.
As Steele himself points out, there is no guaranteed portability of floating
point code in Common Lisp, and the type breakdown is only a means of providing
an aid for transportation.
Issue 3:
The crux of the matter is the the Common Lisp type system provides an
abstract type system down to some level of specificity, at which point
the type system begins to refer to internal machine-dependent representations.
We see the same problem with floats that exists with fixnums: these types
refer to machine-dependent representations.
One solution to the problem would be to define something like parametric
classes. Instead of writing
(defmethod foo ((x single-float))...)
we would write
(defmethod foo ((x (float 24 56))...)
which would state that x ought to be a floating point number whose
representation has between 24 and 56 bits of mantissa. This solution is
workable to some extent if we limit the paramaters to constants and *,
because there is presumably a mapping between (float x y) and one of the
floating-point type names at defmethod time - the mapping is made upon
``transportation.''
We could make the same argument about fixnums:
(defmethod baz ((x (fixnum 10 *)))...)
indicates that this method ought to be invoked when given a fixed precision
number whose representation has at least 10 bits of information.
When we argue that a programmer wishes to write code that discriminates on
the subtypes of FLOAT, we really argue that he wishes to parameterize his
code based on representation. The CLOS class hierarchy is applicable to
purely abstract types and not to representational types. To say this
again in a different way, there is no descriptive power in a pure name,
and in the case of floating point numbers, we wish to map a description to
a class name and then discriminate.
One can argue that this points out an inherent limitation of CLOS - that
it operates in the abstract type domain rather than in the
representational domain. In its pristine form, instances in CLOS are dull
DEFSTRUCT-like objects, and many of the aspects of pristine CLOS as well
as the meta-object protocol are based on optimizing the results of this
choice of what instances are.
It therefore only makes sense that when CLOS comes up on a situation where
representational issues dominate that it is found weak.
Selecting the NONE option doesn't solve any problems, it only admits
defeat.
-rpg-
∂27-May-87 1331 Masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 13:30:46 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 11:09:42 PDT
Date: 27 May 87 11:08 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 27 May 87 13:49 EDT
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-110942-1982@Xerox>
I'm vaguely uneasy about allowing any argument reassignment in
call-next-method; normally lexical variables without any external
reference are insensitive to rebinding them to themselves, e.g.,
(lambda (a b c) ... code ...)
is equivalent to
(lambda (a b c) (let ((a a) (b b) (c c)) ... code ...))
The only precondition for this transformation is that there is no
reference to the variables outside of the scope of the rebinding.
When call-next-method pays attention to reassignment, I presume that it
is only reassignment of the original lexical variables (am I wrong?)
(defmethod frob ((a widget) b c)
.. (setq a (make-widget ...))
...
(call-next-method) ...))
that this would not be the same as
(defmethod frob ((a widget) b c)
(let ((a a))
.. (setq a (make-widget ...))
...
(call-next-method) ...)))
right?
∂27-May-87 1604 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 16:04:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 14:04:08 PDT
Date: 27 May 87 14:03 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Masinter.pa's message of 27 May 87 11:08 PDT
To: Masinter.pa@Xerox.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-140408-2308@Xerox>
I don't believe we are saying that rebinding or changing the value of a
binding would affect call-next-method. Rather, I think we are talking
about another form of call-next-method which would allow arguments to be
passed to it explicitly.
∂27-May-87 1604 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 16:04:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 14:08:28 PDT
Date: 27 May 87 14:08 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Masinter.pa's message of 27 May 87 11:08 PDT
To: Masinter.pa@Xerox.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-140828-2315@Xerox>
I was proposing that call-next-method be given arguments
(defmethod frob ((a widget) (b integer) c)
...
(call-next-method a (sub1 b) c) ...))
where the values given to call-next-method are checked against the
original bindings of the parameters. (call-next-method) uses the
original parameters, and is insensitive to rebindings.
So (defmethod frob ((a widget) b c)
.. (setq a (make-widget ...))
...
(call-next-method) ...))
should be the same as
(defmethod frob ((a widget) b c)
(let ((a a))
.. (setq a (make-widget ...))
...
(call-next-method) ...)))
∂27-May-87 1605 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 16:05:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 15:35:16 PDT
Date: 27 May 87 15:35 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 27 May 87 13:49 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-153516-2470@Xerox>
It seems to me that the whole notion of a 'class discriminated
parameter' is a little problematic. After all, any parameter which is
not an 'individual discriminated parameter' is class discriminated; the
default discrimination of an argument is T. This is not a mute point
since there is no rule that says that someone can't make a class which
has no supers at all (hence an entire different root node).
Also it seems that Danny's example is an excellent example of why we
can't compile the rule that you can't change the applicable set of
methods down into the compilations he gives.
Specifically, Danny's "Assume different behaviors for integer and
floating point input to the gauge" finesses too important a point.
If you had a gauge which just had a method like this:
(defmethod display-value ((g gauge) v)
... show the value ...)
You would want to implement the bounded gauge method like this:
(defmethod display-value ((g bounded-gauge) v)
(with-slots (g)
(call-next-method g (min v max-reading))))
You wouldn't want to have to say:
(defmethod display-value ((g bounded-gauge) v)
(with-slots (g)
(call-next-method g (number-coerce v (min v max-reading)))))
The point is that while the first method on bounded gauge might change
the class of the argument (it could change 151.23 to 100) it wouldn't
change the set of applicable methods. I think this shows why the stated
rule must be:
"The set of methods applicable to a changed set of arguments for
call-next-method must be the same as set of applicable methods for
the
original arguments to the method"
Not any of the proposed compilations of that rule.
Also, we will presumably want APPLY-NEXT-METHOD in addition to
call-next-method.
∂27-May-87 1753 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
Received: from [192.10.41.223] by SAIL.STANFORD.EDU with TCP; 27 May 87 17:53:09 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 133080; Wed 27-May-87 20:37:44 EDT
Date: Wed, 27 May 87 20:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <870527-153516-2470@Xerox>
Message-ID: <870527203752.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 27 May 87 15:35 PDT
From: Gregor.pa@Xerox.COM
Also, we will presumably want APPLY-NEXT-METHOD in addition to
call-next-method.
No, we changed call-next-method from a macro to lexically local function
so that you could just say (apply #'call-next-method ...).
∂27-May-87 1909 kahn.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 19:09:51 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 27 MAY 87 16:18:36 PDT
Date: Wed, 27 May 87 16:18:15 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-Reply-To: <870527-153516-2470@Xerox>
To: Gregor.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Bobrow.pa@Xerox.COM,
common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-161836-2566@Xerox>
> After all, any parameter which is not an 'individual discriminated
parameter'
> is class discriminated; the default discrimination of an argument is
> T. This is not a mute point since there is no rule that says that
someone
> can't make a class which has no supers at all (hence an entire
different
> root node).
Does this mean that PCL is incorrect in its implementation of method
lookup when some of the arguments are specified as instances of T? The
point is that allowing for another root node can be very expensive.
References
Gregor's message of Wed, 27 May 87 15:35:00 PDT -- Re: Arguments to
CALL-NEXT-METHOD
∂27-May-87 1910 Gregor.pa@Xerox.COM OK, I stand corrected
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 19:10:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 18:08:33 PDT
Date: 27 May 87 18:08 PDT
From: Gregor.pa@Xerox.COM
Subject: OK, I stand corrected
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870527-180833-2712@Xerox>
For the next 3 days, you will find me in my office, writing the
following on my whiteboard 1000 times.
moot n. 1. An ancient English meeting, especially a representative
meeting of the freemen of a shire. 2. An imaginary case argued by law
students as an exercise. --tr.v. mooted, mooting, moots. 1. a. To offer
as a subject for debate; bring up for discussion. b. To discuss or
debate. 2. To plead or argue (a case) in a moot court. --adj. 1.
Subject to debate; arguable; unresolved: a moot question. 2. Law.
Without legal significance, through having been previously decided or
settled; of only academic importance. [Middle English mot, moot, Old
English mot, moot, assembly. See mod- in Appendix.]
mute adj. muter, mutest. 1. Refraining from producing speech or vocal
sound. 2. a. Unable to speak. b. Unable to vocalize, as certain animals.
3. Law. Refusing, as a defendant, to plead either guilty or not guilty
when under arraignment. Used chiefly in the phrase stand mute. 4.
Phonetics. a. Not pronounced; silent, as the e in house. b. Pronounced
with a temporary stoppage of breath, as the sounds of p and b; plosive;
stopped. --See Synonyms at dumb. --n. 1. A person incapable of speech;
especially, one both deaf and mute. 2. Law. A defendant who refuses to
plead either guilty or not guilty when under arraignment. 3. Music. Any
of various devices used to muffle or soften the tone of a musical
instrument. 4. Phonetics. a. A silent or unpronounced letter. b. A
plosive; a stop. --tr.v. muted, muting, mutes. 1. To muffle or soften
the sound of. 2. To soften the tone, color, shade, or hue of. [Middle
English muet, from Old French, diminutive of mu, mute, from Latin mutus,
silent, dumb. See mu- in Appendix.] --mute"ly adv. --mute"ness n.
dyslexics of america
untie!
∂27-May-87 1910 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 19:10:28 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 18:11:37 PDT
Date: 27 May 87 18:11 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Gregor.pa's message of 27 May 87 15:35 PDT
To: Gregor.pa@Xerox.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Bobrow.pa@Xerox.COM,
common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-181137-2717@Xerox>
I think this shows why the stated rule must be:
"The set of methods applicable to a changed set of
arguments for call-next-method must be the same as set of
applicable methods for the original arguments to the method"
Not any of the proposed compilations of that rule.
I will revise my deinition slightly to try to save my proposed
compilation.
Any parameter that is specialized by any class other than T, and is not
specialized by an individual is "class discriminated". For any of those
arguments, not changing the class is sufficient to ensure that the set
of applicable methods is not changed.
For my example, in which there was specialization on the class of v was
done, it is necessary to write:
(defmethod display-value ((g bounded-gauge) v)
(with-slots (g)
(call-next-method g (number-coerce v (min v max-reading)))))
∂27-May-87 1910 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 May 87 19:09:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 MAY 87 16:24:04 PDT
Date: 27 May 87 16:23 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Ken Kahn <Kahn.pa>'s message of Wed, 27 May 87 16:18:15 PDT
To: Kahn.pa@Xerox.COM
cc: Gregor.pa@Xerox.COM, Moon@STONY-BROOK.SCRC.Symbolics.COM,
Bobrow.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870527-162404-2575@Xerox>
Date: Wed, 27 May 87 16:18:15 PDT
From: Ken Kahn <Kahn.pa>
Does this mean that PCL is incorrect in its implementation of
method lookup when some of the arguments are specified as instances
of T? The point is that allowing for another root node can be very
expensive.
Uh, sorry. Right, confusion and stuff.
The rest of my message still applies. Namely, I think we have to make
the rule that you can't change the set of applicable methods.
∂28-May-87 0413 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 04:13:05 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 27 May 87 19:10:12 pdt
Received: by hplabsc ; Wed, 27 May 87 18:54:40 pdt
Date: Wed, 27 May 87 18:54:40 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705280154.AA13174@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@sail.stanford.edu
Subject: Re: Arguments to CALL-NEXT-METHOD
This sounds good. I second the motion to call it a decision.
jak
∂28-May-87 0804 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 08:03:52 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 28 May 87 08:03:44 pdt
Received: by hplabsc ; Thu, 28 May 87 08:02:57 pdt
Date: Thu, 28 May 87 08:02:57 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705281502.AA19075@hplabsc>
To: Masinter.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: Arguments to CALL-NEXT-METHOD
>I'm vaguely uneasy about allowing any argument reassignment in
>call-next-method; normally lexical variables without any external
>reference are insensitive to rebinding them to themselves, e.g.,
>
My understanding was that rebinding would not be allowed, but
that passing of arguments would. Thus:
(defmethod frob ((a widget) b c)
(call-next-method (make-widget ...) b c)
)
This would make the arguments explicit, rather than relying on
binding.
jak
∂28-May-87 0856 kempf%hplabsc@hplabs.HP.COM Re: Floats
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 08:56:12 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 28 May 87 08:55:34 pdt
Received: by hplabsc ; Thu, 28 May 87 08:54:39 pdt
Date: Thu, 28 May 87 08:54:39 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705281554.AA19596@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Floats
>One solution to the problem would be to define something like parametric
>classes. Instead of writing
>
>(defmethod foo ((x single-float))...)
>
>we would write
>
>(defmethod foo ((x (float 24 56))...)
>
>which would state that x ought to be a floating point number whose
>representation has between 24 and 56 bits of mantissa. This solution is
>workable to some extent if we limit the paramaters to constants and *,
>because there is presumably a mapping between (float x y) and one of the
>floating-point type names at defmethod time - the mapping is made upon
>``transportation.''
Or, alternatively, provide some means to extend STANDARD-TYPE-CLASS
for particular implementations of CLOS so that programmers could
write:
(defmethod foo ((x float-with-24-56-bits-mantissa) ...)
The extension could be done by implementors of CLOS for particular
hardware, and information on it could be provided through the
*FEATURES* flag (CLtL, pg. 448) so it could be used in readtime
conditionals, if necessary.
With regard to paramatetric classes, I think this is opening up
a whole new can of worms, which we may want to think seriously
about opening at this stage of the game. Languages like Eiffel
and (via generic packages) Ada have them, and there is no reason
that they couldn't be added to Common Lisp, but I would be reluctant
to write that into the standard, until the issues are better understood.
In particular, the interaction between multiple inheritance and
parameterized classes could potentially be quite complex.
>We could make the same argument about fixnums:
>
>(defmethod baz ((x (fixnum 10 *)))...)
>
>indicates that this method ought to be invoked when given a fixed precision
>number whose representation has at least 10 bits of information.
True.
>One can argue that this points out an inherent limitation of CLOS - that
>it operates in the abstract type domain rather than in the
>representational domain. In its pristine form, instances in CLOS are dull
>DEFSTRUCT-like objects, and many of the aspects of pristine CLOS as well
>as the meta-object protocol are based on optimizing the results of this
>choice of what instances are.
The instance creation protocol which is currently being discussed
actually deals with this issue. To a certain extent, the metaobject
protocol is the place for representation to be handled (in my opinion).
STANDARD-TYPE-CLASS is an example of a metaclass with a different
representation than STANDARD-CLASS, as is STANDARD-STRUCTURE-CLASS.
I could imagine a STANDARD-PERSISTENT-CLASS, which has instances
in a database or in the file system, or STANDARD-CD-ROM-CLASS, with
instances which are CD-ROM video or audio images.
>Selecting the NONE option doesn't solve any problems, it only admits
>defeat.
Well, I wouldn't put it that way. I think Larry's comment was appropriate.
The problem is not so much with CLOS as with how the Common Lisp type
system was put together (as was mentioned earlier in this note).
In my opinion, that should be where the problem is fixed.
jak
∂28-May-87 1158 Masinter.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 11:58:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 MAY 87 11:31:40 PDT
Date: 28 May 87 11:30 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Thu,
28 May 87 08:02:57 pdt
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870528-113140-3619@Xerox>
I am embarrased that I totally misunderstood the call-next-method
proposal.
What does (call-next-method) do with optional arguments which have been
defaulted? Does it pass down the values as defaulted or does it
re-default them?
What about optionals which are left out of call-next-method?
∂28-May-87 1251 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 12:51:12 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 28 May 87 12:49:46 pdt
Received: by hplabsc ; Thu, 28 May 87 12:33:11 pdt
Date: Thu, 28 May 87 12:33:11 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705281933.AA21877@hplabsc>
To: Masinter.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: Arguments to CALL-NEXT-METHOD
>What does (call-next-method) do with optional arguments which have been
>defaulted? Does it pass down the values as defaulted or does it
>re-default them?
Good question. Off the top of my head, I'd suggest redefaulting. Any
objections?
>What about optionals which are left out of call-next-method?
Again, I'd assume they default. The model is that CALL-NEXT-METHOD
acts like FUNCALL or APPLY of the method, except method lookup is
short-circuited so the next applicable method is used. At least,
that's how I've been looking at it.
jak
∂28-May-87 1458 Bobrow.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 14:58:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 MAY 87 14:56:56 PDT
Date: 28 May 87 14:56 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Thu,
28 May 87 12:33:11 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: Masinter.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870528-145656-3982@Xerox>
What does (call-next-method) do with optional arguments
which have been defaulted? Does it pass down the values as
defaulted or does it re-default them?
Good question. Off the top of my head, I'd suggest
redefaulting. Any objections?
Isn't there an efficiency (implementation) argument that makes it much
more expensive to do this. If Gregor's early suggestion of
"unpassed-argument" as a value were used for values of optional
arguments that were not passed, then things would be different I think.
∂28-May-87 1511 kempf%hplabsc@hplabs.HP.COM Re: Arguments to CALL-NEXT-METHOD
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 15:10:56 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 28 May 87 15:10:06 pdt
Received: by hplabsc ; Thu, 28 May 87 15:09:09 pdt
Date: Thu, 28 May 87 15:09:09 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8705282209.AA23894@hplabsc>
To: Bobrow.pa@Xerox.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
Cc: Masinter.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
What does (call-next-method) do with optional arguments
which have been defaulted? Does it pass down the values as
defaulted or does it re-default them?
Good question. Off the top of my head, I'd suggest
redefaulting. Any objections?
Isn't there an efficiency (implementation) argument that makes it much
more expensive to do this. If Gregor's early suggestion of
"unpassed-argument" as a value were used for values of optional
arguments that were not passed, then things would be different I think.
Yes, it could be more expensive, depending on the implementation
of optionals.
∂28-May-87 1532 Gregor.pa@Xerox.COM Re: Arguments to CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 May 87 15:32:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 MAY 87 15:27:32 PDT
Date: 28 May 87 15:27 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Arguments to CALL-NEXT-METHOD
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 28 May 87 14:56 PDT
To: Bobrow.pa@Xerox.COM
cc: kempf%hplabsc@hplabs.HP.COM, Masinter.pa@Xerox.COM,
common-lisp-object-system@sail.stanford.edu
Message-ID: <870528-152732-4022@Xerox>
What does (call-next-method) do with optional arguments
which have been defaulted? Does it pass down the values as
defaulted or does it re-default them?
Good question. Off the top of my head, I'd suggest
redefaulting. Any objections?
Isn't there an efficiency (implementation) argument that makes
it much
more expensive to do this. If Gregor's early suggestion of
"unpassed-argument" as a value were used for values of optional
arguments that were not passed, then things would be different
I think.
The spec is already clear on this point. The arguments are redefaulted.
I see no reason to change the spec on this.
∂28-May-87 2159 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Arguments to CALL-NEXT-METHOD
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 May 87 21:59:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 156444; Fri 29-May-87 00:58:41 EDT
Date: Fri, 29 May 87 00:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Arguments to CALL-NEXT-METHOD
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <870528-152732-4022@Xerox>
Message-ID: <870529005850.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 May 87 15:27 PDT
From: Gregor.pa@Xerox.COM
What does (call-next-method) do with optional arguments
which have been defaulted? Does it pass down the values as
defaulted or does it re-default them?
Good question. Off the top of my head, I'd suggest
redefaulting. Any objections?
Isn't there an efficiency (implementation) argument that makes
it much
more expensive to do this. If Gregor's early suggestion of
"unpassed-argument" as a value were used for values of optional
arguments that were not passed, then things would be different
I think.
The spec is already clear on this point. The arguments are redefaulted.
I see no reason to change the spec on this.
I strongly agree. I also don't believe that there is a significant efficiency
cost.
∂29-May-87 1418 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 May 87 14:18:39 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 157396; Fri 29-May-87 17:17:59 EDT
Date: Fri, 29 May 87 17:18 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation discussion (at last!)
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870523-183530-1635@Xerox>
Message-ID: <870529171806.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 May 87 18:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The following is another proposal for instance allocation....
I have been pondering this for a few days. We're getting close to agreement,
I think, but there are a few things about your proposal that bother me.
In this message, I will comment on excerpts from your message that bother me.
In the next message, I will send out a succinct description of how I
see things working, divided up into "necessary" and "optional" features,
with places identified where decisions between alternatives need to be made.
I will use the terminology introduced by Gregor in his message of May 22.
2) divides the instance creation specification between internal and
interface parts (:initargs option). The external part specifies
allowable arguments to make-instance.
I don't think you've completely succeeded in achieving this goal.
Details below. Actually, I doubt that it is feasible to achieve this
goal without major sacrifices in other goals of the standard.
3) assumes optimization of specific calls to make-instance with quoted
arguments so that creating instances can be fast (see Gregor's recent
message), thus allowing removal of the :constructor option.
I agree that we should defer :constructor until we have figured out the
main part of object creation. I don't agree that it has yet been
demonstrated that :constructor is not needed.
The defclass class options are extended to include:
(:initargs (<initarg-name>
[:slotname <slot-specifier>]
[:default-value-form <form>])*)
Each <initarg-name> is a symbol specified to be a legal argument to
make-instance.
<initarg-name> is an abbreviation for (<initarg-name>).
I have two problems with this. For initargs that initialize slots,
this option contains both the declaration and the specification, but
for initargs implemented by methods, this option contains only the
declaration. That seems inconsistent to me, and inconsistent with
your goal of separating the internal and external parts.
The inclusion of the :default-value-form here seems redundant. For
initargs that initialize slots, there is already a way to specify a
default value form in the slot description. For initargs that are
implemented by methods, there is already a way to specify a default
value form in the method parameter list. This :default-value-form
may be based on :default-initargs in an earlier proposal of mine,
but that was something different; :default-initargs was decoupled
from the declaration and specification of initargs, and indeed would
normally appear in a different class. But :default-value-form here
is tightly coupled to the declaration, and to the specification in
the case of initargs that initialize slots.
For each <initarg-name> that has a <default-value-form>, and
does not appear in the init-plist, MAKE-INSTANCE appends <initarg-name>
<value-of-form> to init-plist.
This could be an efficiency problem. I would prefer it if this did not
have to be done for initargs that have not been specified to be
implemented by methods. Defaulting of initargs that initialize slots
can be handled more efficiently, with no need to construct an actual
list of them.
CLASS-INITARGS class &optional local-only
returns the initargs for a standard-class. setf works with
class-initargs when local-only is T.
In my proposal (coming in the next message) I use naming conventions for
this that are more consistent with the 87-003 document. If you've
changed your mind on what naming conventions should be used for the
meta-object functions, please let me know.
ISSUES raised in messages:
1) Lexical proximity (ie why not have an :initarg slot option)
The criterion for simplicity used here is that there should be
exactly one way of specifying legal initargs-names. This simplifies
code for readers who minimize reading of documentation. Another
argument is that specifying initargs is part of the interface, not the
implementation, and hence does not belong with the slot.
I agree with the philosophy of having only one way to do things, but
these arguments are weak, since your :initargs class-option still mixes
implementation with interface, and since (as you point out just below)
readers of code should find out the legal initarg names through a
suitable tool rather than by blundering through code whose documentation
they haven't read.
In my forthcoming proposal, I went back to the :initarg slot-option because
on the whole I think it comes out simpler and better that way. Either way,
there is lexically adjacent information that from some points of view should
be separate and lexically remote information that from some points of view
should be together. I think the congnitive structure is too complex to be
represented in text, and no Lisp syntax can address all points of view. The
environment tools you suggest below seem like a better answer.
I also believe that it is the environment's responsibility to provide
useful views of the class in addition to the text view in the file; for
example, allowing one to see the set of all slots in a class and all
their effective slot-options. Another such view should show the names
of initarg-names that can be used to initialize particular slots.
I certainly believe in this, and my environment does provide the Flavor
equivalents of these features. They're quite useful in practice.
3) How should methods and initargs be kept in synch
Again I believe this is something that a good environment will help
with. No later than the time when the first instance is created, the
environment can warn the user about :initarg-names that are not used for
methods or slot initialization, and methods with illegal argument names.
On 22 April, Gregor said "why is it that I can't count on the methods
getting all the initargs if I use &rest in the lambda-list?" Note that
you can't have it both ways; if the environment does this checking, you
can't use &rest to do your own implementation of the &key mechanism, because
the environment wouldn't be able to figure out what initargs that method
implements.
INITIALIZE-INSTANCE instance &key &allow-other-keys
is the user's procedural handle on initialization. It uses
standard-method-combination. The primary method on standard-object just
returns the instance. One standard way of using initialize will be to
have :before methods, so that all these methods will be fired.
8) Must the user specify &allow-other-keys and :before for
initialize-instance?
A simple macro can add the first or both of these.
Could you explain to my thick skull why
(defmethod-initialize-instance ((x my-class) &key foo bar) ...)
is preferable to and simpler than
(defmethod initialize-instance ((x my-class) &key foo bar) ...)
I believe that this is another example where the standard should be
augmented by a STANDARD library of useful extensions endorsed by the
committee. Other things in that category for me are the macro for
defining simple-method-combination, and the standard simple
method-combination forms (and, or etc.). This is a fourth layer for the
standard.
I think this is a good idea, but I want to warn that we need to be very
careful in how we execute it. If the standard library is only "endorsed"
and not really part of the standard, it is very easy to fall into a Tower
of Babel situation where everyone has their own slightly incompatible
version of the standard library, programs are not really portable, and
programmers can't really understand each other's code. It would be a
shame if that happened. Perhaps if the standard is organized into a
kernel whose description is smaller and can be read in less time, plus
a library, but both are equally well-specified parts of the standard,
it could work. However, I don't think this approach always works;
sometimes the division between "kernel" and "library" seems arbitrary
and only makes the standard seem more complicated.
∂29-May-87 1430 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation discussion (at last!)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 May 87 14:30:28 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 157424; Fri 29-May-87 17:29:47 EDT
Date: Fri, 29 May 87 17:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation discussion (at last!)
To: Common-Lisp-Object-System@sail.stanford.edu
References: <870416002258.1.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870422172838.5.GREGOR@AVALON.isl.parc.xerox.com>,
<870522-161034-1060@Xerox>,
<870523-183530-1635@Xerox>,
<870527015917.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870529172955.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Object creation seems to divide naturally into eight parts, of which three
are essential and five could optionally be added to provide increased
convenience or customizability. When I say these are optional, I don't mean
that the standard would allow implementations to implement them or not
implement them at their convenience; I mean that we must decide whether to
include them in the proposed standard to gain convenience or customizability,
or to exclude them to gain simplicity or understandability.
I'll discuss how I see each of the eight parts working. I'll use the
declaration/specification/defaulting terminology introduced by Gregor in his
message of 22 May. My language is not precise enough for a final draft, but
I hope the concepts come across clearly this time. For brevity, I have
omitted motivation and philosophy; they have already been discussed in the
mail and can continue to be discussed as needed. In places where there
didn't seem to be a concensus I have included a menu of choices with brief
descriptions.
-foo- means the word foo in italics. FOO means the word foo in boldface.
1. MAKE-INSTANCE and the initarg concept
Objects are created by calling MAKE-INSTANCE. The first argument is a
class or the name of a class, and the remaining arguments are -initargs-
(initialization arguments). Each initarg has a -name-, which is a symbol
(not necessarily a keyword), and a -value-. The arguments to MAKE-INSTANCE,
excepting the first, are alternating names and values of initargs.
MAKE-INSTANCE returns one value, the object that was created.
A programmer -declares- the names of initargs that are valid for a class,
-specifies- the implementation of those initargs (what is done with their
values), and optionally (part 7) supplies -default value forms- for them.
The set of valid initargs for a class is the union of the initargs declared
by the class and its superclasses. MAKE-INSTANCE signals an error if an
initarg is supplied that is not valid.
Inheritance of initarg specifications and defaults is discussed in later
sections.
It is valid for an initarg to be declared more than once, and to be
implemented more than once (for example, an initarg could initialize a slot
and also be used by a method).
We say that an initarg -has a value- if the initarg appears in the arguments
to MAKE-INSTANCE, or if the initarg was defaulted (see part 7).
If the same initarg is given more than once in the arguments to MAKE-INSTANCE,
the leftmost occurrence prevails, as required by Common Lisp.
There is one pre-declared initarg in the standard. Its name is
:ALLOW-OTHER-KEYS, its default is NIL, and its specification is the same as
Common Lisp defines for &KEY argument lists.
2. Initargs that initialize slots
The :INITARG -name- slot-option -declares- an initarg named -name- and
-specifies- that this initarg initializes the slot to which the slot-option is
attached. If the initarg has a value, the value is stored into the slot and
the slot's :INITFORM, if any, is not evaluated. If no initarg specified to
initialize a given slot has a value, then the slot is initialized according to
the :INITFORM (if any).
The :INITARG slot-option is inherited from superclasses. The set of initargs
that initialize a given slot is the union of the initargs declared in :INITARG
slot-options with the same slot name in the class and its superclasses. If
two different initargs that initialize the same slot are given in the
arguments to MAKE-INSTANCE, we have to decide what happens.
2a. The leftmost occurrence in the arguments to MAKE-INSTANCE prevails.
2b. The initarg -declared- by the class that appears earliest in the
class precedence list prevails.
The :INITARG slot-option may be specified more than once for a given slot.
A single initarg can initialize more than one slot if the same initarg name
appears in more than one :INITARG slot-option.
There is no DEFCLASS option that specifies initargs for all the slots,
because that would endorse a particular convention for naming initargs.
3. Initialization methods
After the slots have been initialized, methods for INITIALIZE-INSTANCE are
called. The first argument is the instance and the remaining arguments
are initargs. Defining an INITIALIZE-INSTANCE method that accepts the
value of an initarg with an &KEY parameter -specifies- the implementation
of that initarg. The parameter specifier can also supply a default value
form in the standard way. This default value form affects only the method
in which it appears; it is not a substitute for the facility in part 7.
The value returned by an INITIALIZE-INSTANCE method is ignored; these methods
are used for their side-effects only.
We have to decide between two ways of -declaring- initargs whose
implementation is -specified- by INITIALIZE-INSTANCE methods.
3a. The parameter list of the DEFMETHOD -declares- each &KEY parameter's
keyword-name as an initarg.
3b. Initargs that are not -declared- by a :INITARG slot-option must be
-declared- by a :INITARGS class-option before they can be used. The
syntax is (:INITARGS -name1- -name2- ... ).
We have to decide between two ways of inheriting INITIALIZE-INSTANCE methods.
3c. All INITIALIZE-INSTANCE methods are called, most-specific first.
3d. Standard method combination is used. Normally an INITIALIZE-INSTANCE
method must have a :BEFORE qualifier or use CALL-NEXT-METHOD, otherwise
it would prevent superclasses' initialization methods from being called.
We have to decide whether &REST parameters are allowed in INITIALIZE-INSTANCE
methods.
3e. INITIALIZE-INSTANCE methods must have one required parameter and may
have &KEY parameters; &OPTIONAL and &REST parameters are not permitted.
3f. An INITIALIZE-INSTANCE method may have an &REST parameter, which sees
all of the initargs. ("All" needs to be defined more precisely if the
optional feature of part 7 is adopted; does it necessarily include defaulted
initargs?)
We have to decide whether the parameter list of an INITIALIZE-INSTANCE method
must contain the symbol &ALLOW-OTHER-KEYS.
3g. &ALLOW-OTHER-KEYS is not required.
3h. &ALLOW-OTHER-KEYS is required at the end of every INITIALIZE-INSTANCE
method's parameter list.
EVERYTHING BELOW THIS LINE IS OPTIONAL
4. Allocation methods
The allocation of storage for new instances can be customized by
defining a method for the ALLOCATE-INSTANCE generic function. The
value returned is the instance, with no slot values filled in. The
arguments to an ALLOCATE-INSTANCE method are the same as the arguments
to an INITIALIZE-INSTANCE method, except that the first argument is
the class rather than the instance.
ALLOCATE-INSTANCE uses standard method combination.
There is a default method for ALLOCATE-INSTANCE that does the appropriate
implementation-dependent allocation.
The answers to the choices given in part 3, except for 3c/3d, are identical
for ALLOCATE-INSTANCE and INITIALIZE-INSTANCE methods.
5. MAKE-INSTANCE as a generic function
There are predefined methods for MAKE-INSTANCE selected when the first
argument is a SYMBOL or a STANDARD-CLASS, which implement the behavior
described in part 1. Additional methods can be defined to customize
the behavior of MAKE-INSTANCE for different metaclasses.
6. Initarg accessor functions for class objects
CLASS-DIRECT-INITARGS takes a class and returns a list of symbols that are
names of initargs -declared- for the class.
CLASS-ALL-INITARGS takes a class and returns a list of symbols that are names
of valid initargs for the class.
CLASS-DIRECT-SLOT-INITARGS takes a class and returns a list of
(initarg-name slot-name) lists, with one element for each :INITARG
slot-option in the class.
CLASS-ALL-SLOT-INITARGS takes a class and returns a list of
(initarg-name slot-name) lists, with one element for each :INITARG
slot-option in the class and its superclasses.
7. Defaulting of initargs
A -default value form- can be supplied for an initarg, remotely from the
class that -declares- the initarg's validity and -specifies- the initarg's
implementation.
The :DEFAULT-INITARGS class-option is followed by alternating initarg
names and forms. This class option can appear more than once in a DEFCLASS,
but an error is signalled if an initarg name appears more than once in
:DEFAULT-INITARGS class-options.
This class option is inherited; the set of initargs for a class that are
defaulted is the union of the sets of initargs specified in
:DEFAULT-INITARGS class-options of the class and its superclasses. When
more than one default value form is supplied for a given initarg, the
default value form supplied by the class that appears earliest in the class
precedence list is used.
If an initarg for a class is defaulted, it always -has a value-. If the
initarg does not appear in the arguments to MAKE-INSTANCE, the default
value form is evaluated in the lexical environment of the DEFCLASS form
that supplied it and the resulting value is used as the initarg's value.
The CLASS-DIRECT-INITARG-DEFAULTS function takes a class and returns a
list of (initarg-name default-value-form) lists, with one element for each
:INITARG slot-option in the class.
The CLASS-ALL-INITARG-DEFAULTS function takes a class and returns a
list of (initarg-name default-value-form) lists, with one element for each
:INITARG slot-option in the class and its superclasses.
8. Constructors
I think we should defer talking about the details of constructors, or
even deciding whether or not they are needed, until we have settled the
main part of object creation. So I've deleted part 8 of my discussion.
∂29-May-87 1818 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 May 87 18:18:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 MAY 87 18:17:21 PDT
Date: 29 May 87 18:17 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Object creation discussion (at last!)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 29 May 87 17:18 EDT
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870529-181721-1169@Xerox>
Answers to some of the smale questions in your first message:
8) Must the user specify &allow-other-keys and :before
for initialize-instance?
A simple macro can add the first or both of these.
Could you explain to my thick skull why
(defmethod-initialize-instance ((x my-class) &key foo bar) ...)
is preferable to and simpler than
(defmethod initialize-instance ((x my-class) &key foo bar) ...)
My belief was that
(defmethod-init ((x-my-class) &key foo) ...)
would be preferable for some people to
(defmethod initialize-instance :before
((x-my-class) &key foo &allow-other-keys) ...)
Because of its greater conciseness. I would be happy to do without,
since I thin the latter is clearer. Especially since I was not allowing
a new method combination form, and seeing the :before is a useful
reminder. So this special macro has only weak support from me.
I believe that this is another example where the
standard should be augmented by a STANDARD library of useful
extensions endorsed by the committee. Other things in that
category for me are the macro for defining
simple-method-combination, and the standard simple
method-combination forms (and, or etc.). This is a fourth
layer for the standard.
I think this is a good idea, but I want to warn that we need to
be very careful in how we execute it. If the standard library is
only "endorsed" and not really part of the standard, it is very
easy to fall into a Tower of Babel situation where everyone has
their own slightly incompatible version of the standard library,
programs are not really portable, and programmers can't really
understand each other's code. It would be a shame if that
happened. Perhaps if the standard is organized into a kernel whose
description is smaller and can be read in less time, plus a
library, but both are equally well-specified parts of the standard,
it could work. However, I don't think this approach always works;
sometimes the division between "kernel" and "library" seems
arbitrary and only makes the standard seem more complicated.
My idea here is that instead of providing a specification for things in
the library, we provide reference code that is part of the standard. It
is expected that it is this code OR CODE THAT HAS IDENTICAL EFFECT that
will be provided in the system IF ANYTHING BY THIS NAME IS IN THE
SYSTEM.
∂29-May-87 2300 RPG Object Creation (at last!)
To: common-lisp-object-system@SAIL.STANFORD.EDU
In case people care, I am now relatively back in the loop on CLOS.
I have been reading the initialization messages since last weekend
trying to understand them.
I am on the midst of writing a message with an alternative to
Moon's proposal. My proposal is less involved, more radical, more
CLOSsy than Moon's. So that people will not think that I am
lending support to Moon's proposal by my silence, I want to make
clear that I regard Moon's proposal as an abomination. Unless some
revelation comes to me that convinces me it's the right approach
(contrast this with being convinced it's the right thing) adoption
of his proposal is sufficient for me to withdraw my support of CLOS.
-rpg-
∂31-May-87 1313 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 May 87 13:13:45 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 31 MAY 87 13:13:16 PDT
Date: 31 May 87 13:12 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 29 May 87 17:29 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
cc: Gregor.pa@Xerox.COM, Bobrow.pa@Xerox.COM
Message-ID: <870531-131316-1924@Xerox>
This message outlines a different approach for handling initargs which
initialize slot values. The basic idea is that all initarg processing
should be defined procedurally, and so should be moved into
initialize-instance methods. An effect of this is that -specification-
as defined in my earlier message disappears from defclass. In this
'proposal' defclass only does initarg -declaration- and -defaulting-.
I will present this idea in the form of a sketchy proposal and some
comments. This proposal certainly not fully fleshed out, but I believe
it is well enough worked out that we can use it as a basis for talking
about what it would be like to make all initarg processing be defined in
a procedural way.
In this proposal, there are two defclass options, a new macro called
intialize slots, and make-instance works differently than in previous
proposals.
The two defclass options:
- :legal-initargs
This just -declares- the legal initargs for this class. This
option is inherited in the obvious simple way. The set of legal
initargs for a given class is the union of the legal-initargs of
all the classes in the class precedence list.
- :default-initargs
This is used to -default- values for initargs. Notice that it is
completely orthogonal to -declaration-.
Here are a couple examples of using defclass with these options:
;;;
;;; position is an abstract class. It doesn't make sense to make
;;; instance of it all by itself. It has to be mixed in with a
;;; class which handles the :x-position and :y-position initargs.
;;;
(defvar *default-position-x* 0)
(defvar *default-position-y* 0)
(defclass position () ()
(:default-initargs :x-position *default-position-x*
:y-position *default-position-y*))
(defclass x-y-position (position) (x y)
(:legal-initargs :x-position y-position))
The initialize-slots macro is used in initialize-slots methods to help
in processing initargs which initialize slot values. Here is an example
of using it:
(defmethod initialize-instance :before
((p x-y-position) &allow-other-keys &rest initargs)
(initialize-slots p initargs
(:x-position x)
(:y-position y)))
This macro just expands into something like:
(defmethod initialize-instance :before
((p x-y-position) &allow-other-keys &rest initargs)
(apply #'(lambda (&key ((g001 :x-position)) ((g002 :y-position)))
(setf (slot-value p 'x) g001)
(setf (slot-value p 'y) g002))
initargs))
make-instance proceeds by:
1: taking the initargs it is passed and combining them with the
:default-initargs to get the total set of defaulted initargs.
2: calling allocate-instance with the class and the total set of
defaulted initargs to get the new instance.
3: evaluating ALL of the slot :initforms and setting the values of the
slots as specified.
4: calling initialize-instance with the new instance and the complete
set of defaulted initargs.
5: returning the instance.
COMMENTS:
Obviously, the major change in this proposal is that all initarg
processing is defined procedurally using lisp and other primitive
mechanisms of CLOS. I think this is a significant difference. It is
the driving force behind this proposal. Without going into details now,
all the general advantages of using a procedural mechanism based on lisp
rather than a special purpose declarative mechanism apply.
One point I should make is that I don't believe this protocol will run
any slower than previous protocols in cases where the two do the same
work. To be specific, I believe that it is possible, and in fact not
difficult, to make this protocol be as efficient as the new flavors
mechanism for cases where the two are equivalent. Because this is an
important issue I think we should address it explicitly but I would like
to do so in a different message.
Notice (I am sure you have already) that in this proposal, the
:initforms are ALWAYS evaluated. My answer to this is that I consider
that a feature of this proposal. One way of looking at what was
happening before is that there was a declarative mechanism for
specifying that an :initform should not be evaluated if certain initargs
were present. As with all such declarative mechanisms, only certain
pre-defined patterns of such conditionalization were supported. In this
new proposal, if you have an internal initial value (:initform) which
you only want to evaluate if certain initargs are not supplied, move it
to the initialize-instance method for that class. There you can do all
the fancy conditional evaluation you want.
∂31-May-87 1439 masinter.pa@Xerox.COM Re: Object Creation (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 31 May 87 14:39:23 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 31 MAY 87 14:38:53 PDT
From: masinter.pa@Xerox.COM
Date: 31 May 87 14:38:27 PDT
Subject: Re: Object Creation (at last!)
In-reply-to: RPG@SAIL.STANFORD.EDU's message of 29 May 87 23:00 PDT
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870531-143853-1952@Xerox>
Everyone has, as their last resort, the withdrawal of support for the
entire proposal. However, I think that we will arrive at a better
standard if we approach it in the spirit of cooperation. I think there
is a shared sense of uneasiness about any unnecessary complexity. I
don't think you need to threaten us with withdrawal for your alternative
to be heard and considered.
Peace,
Larry
∂31-May-87 1644 RPG Object creation discussion (at last!)
To: common-lisp-object-system@SAIL.STANFORD.EDU
I spent a day last weekend reading the discussion about initialization.
I'm not sure I understand the issues very well, and I'm certain I don't
understand them as well as Moon and Gregor. Nevertheless, I believe that
the whole approach needs to be questioned. It might turn out that Moon's
approach is the best of a number of lousy alternatives, but let's give
something else a shot.
The problem of creating an instance is a combination of two things:
allocating storage for the instance and then initializing the slots of the
instance. It makes sense to want to customize various parts of this
process, and a mechanism like the one for changing class seems appropriate
- when an instance is to be created, several generic functions are
invoked, one to allocate storage and the other to initialize the instance;
the user can define methods on those functions. In this message I will
ignore the issue of ALLOCATE-INSTANCE.
DEFCLASS has an :initform slot option, and I imagine that almost everyone
is going to be happy with that. I can imagine adventuresome people will
call the vanilla MAKE-INSTANCE and then do a number of SETF's to get
things right. The question becomes how often a hairier initialization
protocol will be needed.
The most sophisticated uses of initialization involve inheriting
initialization behavior when that behavior is non-trivial. That is,
there is already a means of inheriting the :initform forms, and we now
are questioning how to inherit more complex behavior.
Generic functions and the class hierarchy are the means CLOS provides
for inheriting behavior. It is powerful and sophisticaed, particularly
in terms of of method combination. Inheritance of slot descriptions is
the means for inheriting structure and description. Because simple
initialization and nothing more is frequently needed, the :initform option
was provided as part of the description of a class, whereas initialization
is clearly more like a behavior (like SETF) than a description (like
classes having slots).
Another goal of the initialization protocol is to effect some mapping
between the arguments to MAKE-INSTANCE and the allocation/initialization
activities. During the process we'd like defaulting to happen as well.
I don't see that initialization is a declarative process; furthermore,
considering it to be declarative leads to the use of a
programming-in-keywords style, which is odious. The only sense in which
it ought to be declarative is that that is a more natural means for
achieving goal of literally declaring the valid arguments to MAKE-INSTANCE.
Other than that, the only motivation for making hairy initialization
declarative is that simple initialization is declarative.
There seems to be another goal for the various proposals, which is to
provide a means to specify an external name for a slot, to be used during
initialization, while the internal slot remains hidden.
There is already a feature to provide an alternative name for a slot,
an external name if you will; and that feature is the accessor method.
In fact, with methods and setf methods one can provide a totally
abstract interface to otherwise-uninteresting instance-provided storage.
I believe that the features of a CLOS without an initialization protocol
ought to be powerful enough to write that initialization protocol.
Let's look at a variant of Danny's example; the syntax I use here
to express what the initialization should do is reminiscent of that in the
various proposals:
(defclass point ()
((x :initform 0 :initarg :moosebird1)
(y :initform 0 :initarg :moosebird2))
(:initargs :rho :theta))
The intention is that X and Y are the internal names of slots and that the
user would prefer to use the more mneumonic names of :MOOSEBIRD1 and
:MOOSEBIRD2 to initialize X and Y. The :initargs class option indicates
that RHO and THETA might be supplied instead of MOOSEBIRD1 and MOOSEBIRD2.
(defclass picture (point)
(bitmap saved-bitmap)
(:initargs
(:moosebird2 :default-value-form *screen-top*)
(:image :slotname (bitmap saved-bitmap))))
Here we want the creation of an instance of PICTURE to make the Y (MOOSEBIRD2)
coordinate of the POINT to be *screen-top* if it isn't supplied to
MAKE-INSTANCE. If :IMAGE is supplied, it supplies the value of the slots
BITMAP and SAVED-BITMAP. I think this syntax is more like Danny's than
Moon's, but it doesn't matter.
It would seem that generic functions and setf methods ought to be able to
handle the needs of these initialization tasks. One could imagine that a
user would want to write a CLOS program that would classify objects based
on changing hypotheses, and that program would want to perform,
essentially, re-initialization or tasks just like it. If CLOS is not able
to support programming like initialization at the user level using
methods, I think we will have failed in our language design.
I will now try to express the initialization needs of this setup
using methods rather than options and see what happens. I do this
to explore the degree to which we have failed to provide mechanisms
sufficient to perform initialization.
(defclass point ()
((x :initform 0)
(y :initform 0)))
First we'll need some methods for RHO and THETA because these abstract
slots don't appear in the DEFCLASS:
(defmethod rho ((p point))...)
(defmethod theta ((p point))...)
(defmethod-setf rho ((p point)) (rho)...)
(defmethod-setf theta ((p point)) (theta)...)
Sometimes the user will supply an X and a Y and sometimes a RHO and a
THETA when he calls MAKE-INSTANCE. However, when the user supplies an X
and a Y, he will use the names MOOSEBIRD1 and MOOSEBIRD2 (we use English
words so we don't have to apologize).
Here's the DEFCLASS for PICTURE:
(defclass picture (point)
(bitmap saved-bitmap))
When a picture is initialized, we want the Y slot to be initialized
to *screen-top*.
Here's a shot at how this looks if we define methods on INITIALIZE-INSTANCE
ourselves:
(defmethod initialize-instance
((p point)
&key (moosebird1 0 mb1-p)
(moosebird2 0 mb2-p)
(rho 0 rho-p)
(theta 0 theta-p)
&allow-other-keys)
;; Maybe we should worry about mixtures of MOOSEBIRD1/MOOSEBIRD2 and
;; RHO/THETA???
(when mb1-p (setf (x p) moosebird1))
(when mb2-p (setf (y p) moosebird2))
;; Something really ugly is in here:
(when (or rho-p theta-p) (let (...) (setf (x p) ...)...))))
Now for initializing PICTURE:
(defmethod initialize-instance
((pict picture)
&key
(moosebird2 *screen-top)
(image nil image-supplied)
&allow-other-keys)
(call-next-method) ;maybe? Or use some method combination?
(when image-supplied
(setf (bitmap pict) image)
(setf (saved-bitmap pict) image))
(setf (y pict) moosebird2))
Hm, well, I'm not sure this is right, but let's move on to look at
MAKE-INSTANCE:
(defmethod MAKE-INSTANCE
((pict picture) &key moosebird1 moosebird2 rho theta image)
(let ((instance (allocate-instance (class-named 'picture)))
(initialize-instance pict moosebird1 moosebird2 rho theta image)))
Well, this seems pretty ugly, plus it's probably wrong. I suppose Moon's
proposal solves all of these problems.
On the other hand, this approach has to look better than this. Generic
functions are supposed to provide modularity and abstraction. Why can't
we achieve it here?
Also, we expect that generic function discrimination should be able to
help us sort out the keyword arguments we need to specify for the
various methods on INITIALIZE-INSTANCE. We've got a lot of logic in
the method on INITIALIZE-INSTANCE for PICTUREs, and that logic looks a
lot like what someone might write to mimic generic function dispatch
if he didn't have it.
Unfortunately, Common Lisp provides bad language design exactly at the
point where we want to attack the problem.
Consider the nature of parameters to functions. In Common Lisp there are
these two notions: positional arguments and named arguments. In the first
case values are associated with variables depending on the positions in
which the arguments are passed. In the latter case, the binding happens
depending on the names of the arguments, which are passed along with the
arguments.
For example:
(defun f (x y &key a b) ...)
(f 1 2 :b 3 :a 4)
X and Y are positional, and A and B are named.
There is a second pair of notions: required arguments and optional arguments.
Does Common Lisp have all of the combinations of these notions?
| positional | named |
-------------------------------
required | yes | no |
-------------------------------
optional | yes | yes |
-------------------------------
It doesn't seem so. Keyword arguments combine named and optional.
We discriminate in generic functions based on required arguments. Suppose
we had named required arguments as distinct from named optional arguments,
and suppose we discriminated on the classes of all required arguments
and on the names of the named required arguments.
(defmethod foo (x y &required-key foo bar) `(foobar ,x ,y ,foo ,bar))
(defmethod foo (x y &required-key baz ola) `(bazola ,x ,y ,baz ,ola))
The behavior I imagine is demonstrated here:
(foo 1 2 :foo 3 :bar 4) => (foobar 1 2 3 4)
(foo 1 2 :baz 3 :ola 4) => (bazola 1 2 3 4)
(foo 1 2 :foo 3 :ola 4) => error
(foo 1 2 :foo 3 :bar 4 :ola 5) => error
Of course, required keyword arguments can be discriminated on in the usual
way as well.
Consider a slightly different pair of methods:
(defmethod foo (x y &required-key foo bar &allow-other-keys)
`(foobar ,x ,y ,foo ,bar))
(defmethod foo (x y &required-key baz ola &allow-other-keys)
`(bazola ,x ,y ,baz ,ola))
One question is which of the two methods on FOO above is more specific
than the other? That is, suppose we write
(foo 1 2 :foo 3 :bar 4 :baz 5 :ola 6)
Which method in invoked?
The answer depends on whether one subscribes to the idea that a total
ordering on methods is necessary, once the arguments are known. I think
it isn't necessary, and I am willing to adopt either one or several
approaches. One is that the ordering is unspecified and effectively
random. The second is that some ambiguous uses of &required-keys (with
&allow-other-keys or :allow-other-keys t) only might make sense within
certain method combination regimes. The regime I will use in the examples
below explicitly are indicated with the qualifier :progn - using it, all
applicable methods are applied.
[Aside:
One could go further with this approach, but it isn't needed for the purposes
of doing initialization in the example shown. Here is the extension of this
approach for the curious reader:
Let's also suppose that if no method on a generic function has optional
arguments, discrimination happens only among methods with the corresponding
numbers of supplied arguments:
(defmethod foo (x) 'one-argument)
(defmethod foo (x y) 'two-arguments)
(defmethod foo (x y z) 'three-arguments)
(foo 1) => one-argument
(foo 1 2) => two-arguments
(foo 1 2 3) => three-arguments
Notice that we no longer have a need for optional arguments at all! Here's
an example:
(defun foo (x &optional (y 77 y-supplied))<code>)
=>
(flet ((f (x y y-supplied) <code>))
(defmethod foo (x y) (f x y t))
(defmethod foo (x) (f x 77 nil)))
or your favorite alternative. of course, when we add in optional keyword
arguments this can get tiresome.]
One major problem with this approach is that it is a generalization of the
notion of generic function in a direction none of us has ever bought
into before. Currently a generic function is a mechanism for examining the
classes of some of the arguments supplied to it and deciding which
method or methods to invoke and how to combine them if more than one
is invoked. This generalization alters that to be as follows:: A generic
function is a mechanism for examining the arguments supplied to it and
deciding which method or methods etc.
Currently we discriminate on the class or identity of an argument, the latter
being similar to a singleton class. This proposal allows us to discriminate
on the name of an argument, and maybe we don't want to do that.
Now let's look at initialization on the above example using the notion
of &required-keys.
(defclass point ()
((x :initform 0)
(y :initform 0)))
(defmethod initialize-instance :progn
((p point) &required-key moosebird1 moosebird2 &allow-other-keys)
(setf (x p) moosebird1)
(setf (y p) moosebird2))
I use the method qualifier ``:progn'' to signify that all the methods that
are applicable are run. I suppose this is in most-general to least-general
order. If some other combination order is correct, that fact is
unimportant to my exploration. Notice that the &required-keys serve to
map the names MOOSEBIRD1 and MOOSEBIRD2 onto the slots named X and Y.
Additionally, the &required-keys select this method based on the named of
the named arguments.
(defmethod initialize-instance :progn
((p point) &required-key rho theta &allow-other-keys)
(let (...)
(setf (x p)...)
(setf (y p)...)))
Either the method for MOOSEBIRD1/MOOSEBIRD2 or the one for RHO/THETA is
selected based on which pair of named arguments are supplied to
MAKE-INSTANCE. If we are willing to expect that any combination might
be supplied, we can write:
(defmethod initialize-instance :progn
((p point) &required-key moosebird1 &allow-other-keys)
(setf (x p) moosebird1))
(defmethod initialize-instance :progn
((p point) &required-key moosebird2 &allow-other-keys)
(setf (y p) moosebird2))
and so on.
Now let's look at PICTURE:
(defclass picture (point)
(bitmap saved-bitmap))
(defmethod initialize-instance :progn
((pict picture) &required-key image &allow-other-keys)
(setf (bitmap pict) image)
(setf (saved-bitmap pict) image))
(defmethod initialize-instance :progn
((pict picture) &key (moosebird2 *screen-top*) &allow-other-keys)
(setf (y pict) moosebird2))
Now MAKE-INSTANCE is easy, as it was before:
(defmethod MAKE-INSTANCE
((pict picture) &rest all)
(let ((instance (allocate-instance (class-named 'picture)))
(apply #'initialize-instance pict all))))
This is definitely more verbose than the other proposals, but it is verbosity
used in rare occasions. Also, the conceptual overhead is lower, because
programmers will already need to know how to write methods and will already
understand how to combine them. Finally, the new aspect of method discrimination
that makes this approach palatable has additional expressive power.
Maybe we don't want to go with an approach like this one, but I think that
the needs of people who would want to write a program whose actions are
like initialization are important enough that we should make sure that
CLOS can handle them.
-rpg-
∂01-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Jun 87 21:32:30 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 161293; Tue 2-Jun-87 00:32:04 EDT
Date: Tue, 2 Jun 87 00:32 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870602003210.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Does anyone have a list of the issues that we wanted the cleanup
committee to address? I remember something about being able to put
generic functions into function cells, a couple of things about cleaning
up the builtin types, the type FUNCTION, and the thing about &key
argument indicators that aren't keywords. The latter two have been
taken care of, the former two haven't and I'm not sure I remember them
too well. Were there any others?
∂02-Jun-87 1029 RPG object / cleanup subcommittee interaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
I assumed that a generic function was a function and so could appear in
a function cell. Doesn't the Concepts chapter state that
(typep <generic function> 'function) => T
I presume that a generic function is a function under the cleaned-up
definition.
Moon, do you know the date of your message discussing the non-keyword &key
arguments? What are the considerations?
I think there were no other problems except for a recommendation to
design a DEFRECORD facility to replace DEFSTRUCT now that DEFSTRUCT is
sort of obsolete.
-rpg-
∂02-Jun-87 1203 Bobrow.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 12:03:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 JUN 87 11:48:05 PDT
Date: 2 Jun 87 11:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 02 Jun 87
10:29 PDT
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870602-114805-4200@Xerox>
Other cleanup issues:
Making FUNCTION be a genuine type (distinct from CONS)
Making PATH-NAME, HASHARRAY etc be distinct from other types so we can
have a class
(i.e. making these be distinguishable by the type system from an
implementation type e.g. array)
∂02-Jun-87 1642 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 16:41:55 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 2 Jun 87 16:36:27 pdt
Received: by hplabsc ; Tue, 2 Jun 87 16:35:16 pdt
Date: Tue, 2 Jun 87 16:35:16 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706022335.AA00365@hplabsc>
To: Common-Lisp-Object-System@sail.stanford.edu,
Moon@STONY-BROOK.SCRC.Symbolics.COM
Subject: Re: object / cleanup subcommittee interaction
Yes. The need for a LOAD-TIME-EVAL function. Most lisps have this
functionality anyway, to implement #, but it needs to available
from macrogenerated code as well. I use it in COOL and I believe
it is used in CALL-NEXT-METHOD.
Other than that, something like the LET-PSEUDO which we use in
HP Lisp to implement lexical instance variables would make
WITH-SLOTS somewhat cleaner, by not requiring a code walk. The
general idea is to have a symbol macro facility, which allows
forms to be substituted for symbols. Careful study would be
required to determine where in the macroexpand-evaluate loop
to insert expansion of symbol macros, however.
jak
∂02-Jun-87 2022 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 20:22:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 JUN 87 20:16:33 PDT
Date: 2 Jun 87 18:37 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Gregor.pa's message of 31 May 87 13:12 PDT
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870602-201633-1444@Xerox>
This message proposes another variant on initialization that has in
common with Gregor's and RPG's that it pushes all initialization into
initialization methods. It is most like Gregor's, but has NO new class
options and no new mechanism for calling generic functions. Its
properties are:
1) Legality checking of make-instance arguments is made an environmental
issue.
2) All :initforms are evaluated (as in Gregor's message);
allocate-instance returns an instance with all the values specified by
:initforms filled in.
3) Default values for initargs are computed a special method
4) Standard initialization methods are :after methods, so that more
specialized methods run after less specialized ones. Initialization of
slots is done in these :after methods.
5) Standard macros can provide convenience for the user and allow hooks
into the environment, and probably optimization. By standard I mean in
the sense of my last message, with a reference implementation.
Here is a cut at a more detailed description:
(defmethod make-instance ((c standard-class) &rest initargs)
(let ((o (allocate-instance c)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o)
(defmethod initial-args ((o standard-object) initargs)
initargs)
Suppose for objects of class position one wanted to have
default-initargs :x with default value (compute-x).
Then one would write a method:
(defmethod initial-args ((o position) initargs)
(call-next-method o
(if (get initargs ':x) initargs
(list* ':x (compute-x) initargs))))
The obvious convenient macro would allow one to write
(defmethod-initial-args position (:x (compute-x) :y (compute-y)...))
Suppose one wanted to have :x set the slot x, and :rho to do something
else. One would write
(defmethod initialize-instance :after
((o position) &key (rho :rho) (g002 :x g0002-p)
&allow-other-keys)
(when g0002-p (setf (slot-value x) g002))
... ; do rho stuff)) )
An obvious macro for supporting this might allow
(defmethod-init-after ((o position) &key (rho :rho)) (:x x ...)
... ;do rho stuff)
where defmethod-init-after inserts the :after, &allow-other-keys, and
the arguments used for the slot-value setting, as well as generating
the code.
Arguemnt checking.
I assume here that the set of legal arguments to intialize-instance are
just those that are explicit in some method of initialize-instance, and
some environmental facility will provide appropriate warnings (very fast
hand waving here).
Optimization
I have also ignored any discussion here of how optimized calls to
make-instance could be managed, but I believe it could be done. (more
fast hand waving).
∂03-Jun-87 1220 Bobrow.pa@Xerox.COM Re: Floats
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 12:20:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 11:01:14 PDT
Date: 3 Jun 87 11:01 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Floats
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 May 87
11:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870603-110114-2066@Xerox>
This problem needs to be solved in several parts:
1) We need a way in CLOS to have more than one name for a particular
class. A class should have at most one primary name, the one it
provides as value of (class-named class). I suggest a function
(set-class-name class name &optional primary-name-p)
This will allow us to add names such as FLOAT-24-32 to SHORT-FLOAT
2) We need a mechanism to go from class descriptions to classes,
something like:
(get-class-from-description superclass-name semantic-description).
It would use system dependent descriptions of classes, and a matching
procedure.
e.g. (get-class-from-description
'FLOAT
(AND (MANTISSA 24 32) (EXPONENT 6 10)))
Classes that need such matching might have a property describing
themselves, and a metaclass that knows how to match descriptions, so the
search could be a recursive tree walk from a super.
3) Methods should be defined on semantic-based classes, e.g.
FLOAT-24-32. The real problem for a user is when he/she defines methods
on two classes with different names, and they turn out to be defined on
the same class. Thus one mthod replaces the other. If each method
defined by defmethod remembered the names under which it were defined,
then an appropriate warning could be issued when a replacement of this
kind happened.
4) This solves the FLOAT problem provided CommonLisp has a reasonable
semantics. I do not claim to understand this at all. If it does not,
then this must be solved separately.
∂03-Jun-87 1221 Gregor.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 12:21:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 11:32:13 PDT
Date: 3 Jun 87 11:31 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 2 Jun 87 00:32 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870603-113213-2135@Xerox>
Yes, load-time-eval is, I think an important issue for the cleanup
committee.
I also think that providing constructors and accessors for lexical
environments is important. I don't know what committee that is supposed
to fall under, but it would be good to get it fixed as soon as possible.
As I have said before, I would rather see us do that right than add
symbol macros to the language.
∂03-Jun-87 1455 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 14:55:16 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 3 Jun 87 14:54:34 pdt
Received: by hplabsc ; Wed, 3 Jun 87 14:53:08 pdt
Date: Wed, 3 Jun 87 14:53:08 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706032153.AA14903@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: object / cleanup subcommittee interaction
I second Gregor's proposal for providing constructors and accessors
for lexical environments. Environments are underspecified in
CLtL, resulting in confusion in implementation.
∂03-Jun-87 1709 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 17:09:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 17:00:29 PDT
Date: 3 Jun 87 17:00 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 31 May 87
16:44 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870603-170029-2690@Xerox>
In this message I address what I think is an important point which Dick
happened to mention in his message. Specifically, its important that
whatever the special purpose mechanisms we might want to include in the
initialization protocol are, it should be possible to implement those
using more primitive CLOS.
Specifically, I will look at initarg -defaulting-. I will show that it
is just a specific instance of a more general problem, and I will show
two different ways that problem can be implemented in CLOS. I will also
show how the kinds of optimizations which are desirable can be
implemented in CLOS.
There is a lot of stuff in this message. A lot of this message is
sample code. I know that makes it somewhat dense and I apologize, but I
think the points are important. I hope that at least the following come
across:
- two different ways of thinking about how default initarg inheritance
works.
- how to implement functionality like default initarg inheritance in
CLOS.
- some more examples of the kinds of things the meta-object protocol
is good for.
Initarg defaulting is just a specific instance of the more general
problem of computing a value for a class from component values provided
by all the classes in the class precedence list. Seen as such, there
are two different mechanisms for doing this in CLOS. I will call these
the "structural" and the "procedural" point of view.
In these sample implementations, I will just implement the collection of
the default initargs for a class. These implementations do not take
care of merging the initargs provided in the call to make-instance with
the default values to get the 'total, defaulted, evaluated initargs'.
In a separate message Danny or I will show an interesting way to do that
using the procedural implementation.
In all examples, assume the following class structure, with the
per-class default-initargs as annotated:
menu ((:highlighting :invert)
\ (:expose-near *default-expose-near*))
\
\
color-menu ((:highlighting *highlight-color*))
\
\
editor-menu ((:expose-near *editor-window*))
so that the value returned by
(class-default-initargs (class-named 'editor-menu))
should be
((:expose-near *editor-window*) (:highlighting *highlight-color*))
PROCEDURAL IMPLEMENTATION:
;;;
;;; For each class, define a method on class-default-initargs which
contributes
;;; that class's initargs. The structure is that the initargs for a
particular
;;; class get consed onto the initargs for its superclasses (using
list*). The
;;; primary method on OBJECT provides the NIL for the base of the
consing. The
;;; :around method on OBJECT provides mechanism for removing duplicated
initargs
;;; from the rest of the list.
;;;
(defmethod default-initargs ((c object))
())
(defmethod default-initargs :around ((c object))
(remove-duplicates-from-plist (call-next-method) :from-end 't))
;;;
;;; Here are the methods for the sample classes.
;;;
(defmethod default-initargs ((c menu))
(list* '(:highlighting :invert)
'(:expose-near *default-expose-near*)
(call-next-method)))
(defmethod default-initargs ((c color-menu))
(list* '(:highlighting *highlight-color*)
(call-next-method)))
(defmethod default-initargs ((c editor-menu))
(list* '(:expose-near *editor-window*)))
STRUCTURAL IMPLEMENTATION:
;;;
;;; For classes, define a new class option, :default-initargs, which is
used to
;;; specify the default initargs for that class. The
class-default-initargs
;;; generic function just goes and collects the contributions from all
the
;;; classes merges them together.
;;;
(defclass my-standard-class (standard-class)
((local-default-initargs :initform ()
:accessor class-local-default-initargs)))
;;;
;;; Any class which isn't an instance of my-standard-class has local
default
;;; initargs of (). It is an error to try and set the local default
initargs
;;; of a class which isn't an instance of my-standard-class.
;;;
(defmethod class-local-default-initargs ((class standard-class))
())
(defmethod-setf class-local-default-initargs ((class standard-class))
(nv)
(error "can't set the default initargs of ~S". class))
(defmethod legal-class-option-p ((class my-standard-class) option)
(eq option ':default-initargs))
(defmethod update-class ((class my-standard-class) &key options
&allow-other-keys)
(setf (class-local-default-initargs class)
(getf options :default-initargs))
(call-next-method))
(defun class-default-initargs (class)
(remove-plist-duplicates
(apply #'append
(mapcar #'class-local-default-initargs
(class-precedence-list class))))
:from-end 't))
An obvious problem with both of these implementations is that every time
the class-default-initargs function is called the value is consed up.
Certainly in initialization we would want to be able to optimize this by
caching the result, and it is reasonable to expect that much user code
might want to do so as well. This is also easy to do using CLOS.
PROCEDURAL IMPLEMENTATION (cached version):
In this implementation, in order to make things more simple, we use a
special macro define-default-initargs-method to define the special kinds
of methods on default-initargs. This special macro isn't absolutely
necessary, it just makes the code presented here a little simpler.
(defclass default-initargs-method (standard-method)
((initargs :initform nil
:accessor method-initargs)))
(defmacro define-default-initargs-method (class-name initargs)
`(define-default-initargs-method-1 ',class-name
',initargs
#'(lambda (ignore) ',initargs)))
(defun define-default-initargs-method-1 (class-name initargs fn)
(let* ((class (class-named class-name))
(specs (list class))
(old (get-method #'default-initargs () (list (class-named
class-name)) ()))
(new (make-instance 'default-initargs-method :function fn
:specializers
specs
:initargs
initargs)))
(when old (remove-method #'default-initargs old))
(add-method #'default-initargs new)))
(defgeneric-options default-initargs (class))
;;;
;;; add a method to compute effective method for default-initargs which
will take care of
;;; producing a special effective method when all the methods are of the
special kind.
;;;
;;; if there are any methods on default-initargs that were defined with
defmethod, we will
;;; just revert to ordinary standard method combination. In this way,
we get the optimization
;;; when we can have it, but when someone wants to put a method on
default-initargs that needs
;;; to compute that will work just fine.
;;;
(add-named-method 'compute-effective-method
'(gfun methods type args)
`(',#'default-initargs)
#'(lambda (gfun methods ignore ignore)
(if (every #'(lambda (m) (typep m
'default-initargs-method))
methods)
<make optimized method>
(call-next-method))))
Where <make-optimized-method> produces a method which just has all the
constants collected up in it.
STRUCTURAL IMPLEMENTATION (cached version):
For the structural implementation, much of the code is the same. We
just use the propagate-class-update generic function to maintain a cache
of the proper value. Note that this implementation is not the best
possible. In particular, it recomputes the class-default-initargs
anytime any aspect of a class changes. This is not hard to fix, I have
just done the simplest of the caching implementations here. The reason
being that a more spohisticated structural caching implementations would
have the same structure, it would hook itself into the class update
protocol the same way, but it would be harder to read.
;;;
;;; For classes, define a new class option, :default-initargs, which is
used to
;;; specify the default initargs for that class. The
class-default-initargs
;;; generic function just goes and collects the contributions from all
the
;;; classes merges them together.
;;;
(defclass my-standard-class (standard-class)
((local-default-initargs
:initform ()
:accessor class-local-default-initargs))
(default-initargs
:initform ()
:reader class-default-initargs)))
;;;
;;; A class which isn't an instance of my-standard-class has local and
total
;;; default initargs of (). It is an error to try and set the local
default
;;; initargs of a class which isn't an instance of my-standard-class.
;;;
(defmethod class-local-default-initargs ((class standard-class))
())
(defmethod-setf class-local-default-initargs ((class standard-class))
(nv)
(error "can't set the default initargs of ~S". class))
(defmethod class-default-initargs ((class standard-class))
())
(defmethod legal-class-option-p ((class my-standard-class) option)
(eq option ':default-initargs))
(defmethod update-class ((class my-standard-class) &key options
&allow-other-keys)
(setf (class-local-default-initargs class)
(getf options :default-initargs))
(call-next-method))
(defmethod propagate-class-update ((class my-standard-class)
new-fully-defined-p
old-fully-defined-p
changed-class
&allow-other-keys)
(setf (class-default-initargs class)
(compute-default-initargs class)))
(defun compute-default-initargs (class)
(remove-plist-duplicates
(apply #'append
(mapcar #'class-local-default-initargs
(class-precedence-list class))))
:from-end 't))
∂03-Jun-87 2020 RPG My Message of May 29
To: common-lisp-object-system@SAIL.STANFORD.EDU
In that message I tried to get peoples' attention so that I would make
sure that we did not go too far down the path of something I suspect is an
ad hoc solution to the initialization problem. The point that Gregor
characterizes as something I ``happened to say'' was the main point I was
trying to make - that message was 9 days in the making. In order to get
peoples' attention I used the inflammatory phrasing that solving this
problem in this way would cause me to withdraw my support of CLOS.
Upon reflection, that was a mistake - of course I'm not going to withdraw
my support. I flew off the handle because I think that we have put
together a pretty darn good language with CLOS so far (though it's not
perfect), and I want to make sure we live up to the standards we have set
for ourselves with the work we do to complete it.
It might turn out that Moon's proposed solution is the correct one,
but I want us to explore the alternatives and make sure that there
isn't a whole category of programs we are making hard to write by
not looking at those alternatives now.
You all know that I tend to be outrageous at times, and I do it as part of
the rhetorical game. But I think you all know I've only insisted on one
stupid thing in CLOS so far (the name DEFGENERIC-OPTIONS), so the bluster
cannot mean all that much.
Please accept my apologies and let's get on with the thinking!
-rpg-
∂04-Jun-87 1004 kempf%hplabsc@hplabs.HP.COM SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Jun 87 10:03:40 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 4 Jun 87 10:03:07 pdt
Received: by hplabsc ; Thu, 4 Jun 87 10:02:01 pdt
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706041702.AA04950@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: SETF- method names
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference. However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
jak
∂04-Jun-87 1525 kempf%hplabsc@hplabs.HP.COM Re: object creation / initialization discussion
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Jun 87 15:25:33 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 4 Jun 87 15:25:31 pdt
Received: by hplabsc ; Thu, 4 Jun 87 15:24:22 pdt
Date: Thu, 4 Jun 87 15:24:22 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706042224.AA09308@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: object creation / initialization discussion
I've hesitated to jump into the brouhaha until I had a chance
to review correspondence, and will limit myself to some general
comments, since I think most points of view have been covered.
In particular, I like Dick's analysis, stressing use of features
in the existing CLOS design rather than addition of new, more
complicated features. It does lead to more verbose code for
more complicated applications, thus some applications programmers
will complain, but the simple cases don't require as much conceptual
overhead. The analysis of positional v.s. named arguments in
Common Lisp was interesting. Dick seems to have identified a hole
in the Common Lisp design, which, if correctly filled, could
lead to some simplifications.
His analysis did not touch on order of :INITFORM evaluation, nor
the lexical and dynamic context in which :INITFORM evaluation
occurs. A simple selection of context here would be the lexical
context of the class (as suggested by Danny in an earlier message)
and the dynamic context of one of the methods during MAKE-INSTANCE
invocation. Perhaps the dynamic context could be within MAKE-INSTANCE,
or the ALLOCATE-INSTANCE method, as suggested by Gregor? As for order of
evaluation, perhaps this could be determined by the class precedence
list ordering, for inherited slots, and by lexical ordering within
the DEFCLASS form.
As the 87-002 spec currently stands, the :INITFORM initialization
forms have no reference to previously initialized slots in the
object being initialized, nor can they reference the object being
initialized itself. Dick's proposal seems to imply that the INITIALIZE-INSTANCE
method would be the place for initializations dependent on values
of slots previously initialized to be put. This seems fine with
me. However, I think specifying the order and context of :INITFORM
evaluation is important, for those applications programmers who
feel a need to use side-effects during initialization (however
henious we might find it). If the order and context is not
specified, it will be left up to each implementor to select it,
and thus this aspect of the semantics of initialization will be
determined by the particular implementation rather than the specification.
jak
∂05-Jun-87 2359 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jun 87 23:59:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JUN 87 23:49:40 PDT
Date: 5 Jun 87 23:49 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 2 Jun 87 11:48 PDT
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870605-234940-2970@Xerox>
The cleanup committee is considering proposals for function-type and
non-keyword &Key arguments.
There is no proposal yet submitted for PATHNAME-HASH-TABLE-TYPE-DISTINCT
( making pathname, hash-table separate classes.)
There is no proposal yet submitted for SHARP-COMMA-SPECIAL-FORM.
(load time evaluation function. )
There is no proposal yet submitted for DEFSTRUCT-CLOS.
There is no proposal yet submitted for LEXICAL-ENVIRONMENT-ACCESSORS.
A draft of the proposal format is enclosed. Several proposals were
released last X3J13. Stay tuned to X3J13@Sail.stanford.edu for more
samples...
!
Format for proposals to "clean up" Common Lisp.
Version 10 - 5-Jun-87
Replace the text below in >> double inverted angle-brackets <<. Be
brief; leave testimonials and personal opinions to the discussion at the
end. Be complete; do not expect someone else to fix or redesign parts.
Spell out names (e.g., Masinter rather than LMM) and upcase all Lisp
symbols (DEFUN rather than Defun). I like it better if you write in the
third person rather than first.
Issue: >>A short descriptive label, which starts with a name which
occurs in the index of CLtL, and be a suitable symbol in the Common Lisp
style, e.g., CDR-TERMINATION. .<<
References: >>The pages of CLtL which describe the feature being
discussed, or other references..<<
Category: >>One or more of: CLARIFICATION -- proposal to resolve an
ambiguity or case of under-specified situation in CLtL, where this
ambiguity interferes with portability of code. CHANGE -- proposal for an
incompatible change to the language. ADDITION -- proposal for a
compatible extension to the language. <<
Edit history: >>Author and date of submission (version 1), and author
and date of subsequent versions.<<
Problem description: >>Describe the problem being addressed -- why is
the current situation unclear or unsatisfactory? Avoid describing the
proposal here or arguing for its adoption. <<
Proposal (>>issue-label:proposal-label<<): >> Describe as precisely as
possible what you are proposing. Ideally, this should take the form of
text that could be dropped into CLtL or some new specification document.
If necessary, propose a set of labelled alternatives here, rather than a
single proposal. Each proposal must be a complete design; do not leave
out details. Avoid arguing for the proposal here, just describe it.<<
Test Case: >>When possible, give a sample of Common Lisp code that
illustrates the issue.<<
Rationale: >> A brief argument for the proposal. (If more than one
proposal is listed, discuss each issue separately here and in subsequent
sections.)<<
Current practice: >>Do some/many/no Common Lisp implementations already
work this way? Survey independent Common Lisp implementations -
preferably three or more.<<
Adoption Cost: >>What is the cost to implementors of adopting the
proposal? How much implementation effort is required? Is public-domain
code available? For pervasive changes, can the conversion be
automated?<<
Cost of non-adoption: >>How serious is it if nothing is done? <<
Benefits: >>What is better if the proposal is adopted? How serious is
the problem if just left as it is? <<
Conversion Cost: >>For incompatible changes, what is the cost to users
of converting existing user code? To what extent can the process be
automated? How?<<
Esthetics: >>How does this proposal affect the simplicity of the
language, ease of learning, etc.<<
Discussion: >> Additional arguments, discussions, endorsements,
testimonials, etc. should go here. A blow-by-blow account of debates is
not necessary. <<
∂06-Jun-87 1219 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jun 87 12:18:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JUN 87 12:18:29 PDT
Date: 6 Jun 87 12:18 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Bobrow.pa's message of 2 Jun 87 18:37 PDT
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870606-121829-3209@Xerox>
Let me take a stab at simplifying part of Danny's message. Danny is
proposing that the entire initialization protocol be defined in a
procedural way, using methods that the user defines on specific generic
functions. In particular, Danny is going one step farther than a couple
of the messages that I sent out in that he is proposing that initarg
defaulting and initarg declaration be done procedurally. Originally, I
was only proposing that initarg specification be done procedurally.
I didn't really like this proposal when I first heard it, but I like it
a lot now after thinking about it for a bit more. This message sketches
out in a bit more detail what it would be like:
initarg DEFAULTING.
There are two generic functions involved. class-default-initargs and
merge-initargs.
CLASS-DEFAULT-INITARGS, returns the default-initargs for a given class.
It is the collection of the initargs for all the superclasses inherited
in the obvious way. The class-default-initargs generic function uses
standard method combination. There are two pre-defined methods on
class-default-initargs, these are as described in a message I sent out
earlier in the week:
(defmethod default-initargs ((c object))
())
(defmethod default-initargs :around ((c object))
(remove-duplicates-from-plist (call-next-method) :from-end 't))
Given these methods, a user can define default initargs for a particular
class using methods like the following (also from my message of last
week):
(defmethod default-initargs ((c menu))
(list* '(:highlighting :invert)
'(:expose-near *default-expose-near*)
(call-next-method)))
(defmethod default-initargs ((c color-menu))
(list* '(:highlighting ':red)
(call-next-method)))
MERGE-INITARGS takes the class, the supplied initargs and the default
initargs. It merges the supplied initargs with the default initargs and
returns a complete set of defaulted initargs with the values from the
default initargs evaluated. This value is all set to be passed to the
initialize-instance and allocate-instance generic functions. The
default implementation of this generic function is something like:
(defmethod merge-initargs ((class object) supplied default)
(let ((total nil))
(do-initargs (name val default)
(unless (getf name supplied)
(push name total)
(push (eval val) total)))
(append supplied (reverse total))))
As I showed in my message of last week, its really easy to optimize all
this to run just as fast as constructors do now, so speed is not an
issue here.
Some of the reasons I like this are:
It builds on existing mechanism, people can understand it without
having to understand new mechanism.
Because it builds on documented, primitive mechanism, people can
tailor it new ways. Specifically, if for a certain class, the presence
of a particular initarg means that several default initargs should not
be included in the merge, it is easy for someone to figure out how to do
that. They just define their own method on merge-initargs which
implements that rule.
initarg DECLARATION is real simple.
There is one pre-defined method on class-legal-initargs
(defmethod class-legal-initargs ((class object))
())
Users define methods like:
(defmethod class-legal-initargs ((class plane))
(list* ':speed ':engines (call-next-method)))
If a user wants to explicity override some initargs provided by a
superclass they can do that since everything is procedural and under
their control:
(defmethod class-legal-initargs ((class boat))
(let ((supers (call-next-method)))
(list* ':speed (remove :color supers))))
∂06-Jun-87 1350 RPG Order of Initialization
To: common-lisp-object-system@SAIL.STANFORD.EDU
I thought that we have already specified that the INITFORMs happen
in the lexical context within which the DEFCLASS occurred. If there are
specials in the INITFORMs, I suppose that the dynamic context in which
the MAKE-INSTANCE is evaluated provides the dynamic context.
In terms of the order of evaluation of the INITFORMs, I thought that
the inheritance rules we had for slot descriptions settled which INITFORM
was evaluated to provide the initial value for the slot.
In terms of the order of evaluation of the INITIALIZE-INSTANCE methods, it
always seemed to me that method combination was how we should control
that, but that the most sensible default order was most general to most
specific (that is, like :AFTER).
There are, of course, problems with my &required-key proposal. One is that
unless there is some way to not pass all of the optional arguments, there
is no way to have a function with both required keyword and truly optional
positional arguments.
Suppose someone writes
(defun f (x y &optional a b &key foo bar baz ola)
(list x y a b foo bar baz ola))
and this form is evaluated:
(f <a1> <a2> <a3> <a4> <a5> <a6> <a7> <a8>)
The binding of the variables in the function definition goes like this:
x is bound to <a1>, y is bound to <a2>, a is bound to <a3>, and b is
bound to <a4>. Now we lift our heads from the sand and look at what
<a5> is. It should be one of :foo, :bar, :baz, or :ola. Now suppose
we had written:
(f 1 2 :foo 4 :bar 5 :baz 6)
Did the user intend for a to be bound to :foo, or did he intend for
a and b to not be supplied?
Here is my proposal for lambda expressions; it includes Moon's
proposal for non-keyword package symbols to be names of arguments:
(lambda ({var}*
[&optional {var | (var [initform [svar]])}*]
[&required-key {name}*]
[&rest var]
[&key {var | (name var)} [initform [svar]])}*
[&allow-other-keys]]
[&aux {var | (var [initform])}*])
{declaration | documentation-string}*
{form}*)
where var, initform, svar are exactly as before, and name is the name of
a keyword argument, which can be a symbol in any package. Parsing an
argument list proceeds as follows:
Let nrp be the number of required positional parameters. The first nrp
supplied arguments are paired with the nrp required positional parameters.
The remaining supplied arguments are scanned left-to-right, starting with
scanning for positional optionals. If a supplied argument is EQ to one of
the required named parameters, the scanning for positional optionals ends
and all unpaired positional optionals are defaulted according to the
lambda-list specification; then named parameter parsing begins. If a
supplied argument is not EQ to any required named parameter, it is paired
with the next positional optional parameter.
Once the scanning for optional positional parameters has ended, scanning
for named parameters begins. Named parameter parsing is as in current
Common Lisp, except that if, at the end, there are unsupplied
required named arguments, an error is signaled.
The difference between this parsing algorithm and the current Common Lisp
one is that the occurrence of the first required named parameter stops
parsing of positional optionals. Therefore, the only way to pass the name
of required named parameter is as a required positional or required named
argument. Also, if optional named arguments appear to the left of all
required named arguments, they can be taken as positional optionals.
Examples:
(defun f (x y &optional a b &required-key :foo :bar &key baz ola)
(list x y a b foo bar baz ola))
(f 1 2 3 4 :foo 5 :bar 6 :baz 7 :ola 8)
=> (1 2 3 4 5 6 7 8)
(f 1 2 3 :bar 4 :baz 5 :foo 6 :ola 7)
=> (1 2 3 nil 6 4 5 7)
(f 1 2 :baz 3 :foo 4 :bar 5)
=> (1 2 :baz 3 4 5 nil nil)
(f 1 2 :baz :foo 3 :bar 4)
=> (1 2 :baz nil 3 4 nil nil)
Because of Moon's proposal to not require keywords to be in the keyword
package, this proposal introduces some ugliness, but it uses the well-used
design principle: feel free to introduce ugliness and inconsistency for
new users in order to keep old code working.
-rpg-
∂06-Jun-87 1624 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 6 Jun 87 16:24:20 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Sat, 6 Jun 87 14:27:50 pdt
Received: by hplabsc ; Sat, 6 Jun 87 14:26:48 pdt
Date: Sat, 6 Jun 87 14:26:48 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706062126.AA01592@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Order of Initialization
>
>I thought that we have already specified that the INITFORMs happen
>in the lexical context within which the DEFCLASS occurred. If there are
>specials in the INITFORMs, I suppose that the dynamic context in which
>the MAKE-INSTANCE is evaluated provides the dynamic context.
>
This sounds fine with me. I didn't remember a decision being reached
on the lexical part. The dynamic context of MAKE-INSTANCE is OK, presumably
just before the INITIALIZE-INSTANCE method is called and just after
ALLOCATE-INSTANCE? Otherwise, either the instance doesn't yet exist,
or the user could have done some potential customized initialization
which would be overwritten.
>In terms of the order of evaluation of the INITFORMs, I thought that
>the inheritance rules we had for slot descriptions settled which INITFORM
>was evaluated to provide the initial value for the slot.
My reading of the 87-002 document is that the initialization form
which is run for a particular slot is the first one which is encountered,
searching up the class precedence list. This says nothing, however, about
the order in which the initialization forms for all the slots are run.
This is what I meant. I would suggest that the lexical ordering of
slots within a class determine the order in which the initialization
forms are run for the slots defined by that class, and that the
order of the class precedence list determine the order for the entire
instance.
>In terms of the order of evaluation of the INITIALIZE-INSTANCE methods, it
>always seemed to me that method combination was how we should control
>that, but that the most sensible default order was most general to most
>specific (that is, like :AFTER).
In fact, the rules for method combination and initialization on
pg. 1-21:1-25 could determine this. I can't see any reason to
special case INITIALIZE-INSTANCE.
I'll postpone comments on the &REQUIRED-KEY proposal and Gregor's
proposal for a functional interface to initialization until I've
had a chance to study them.
jak
∂06-Jun-87 1636 RPG Order of Initialization
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Jak sez:
``This says nothing, however, about the order in which the initialization
forms for all the slots are run.''
I respond:
This say everything about how stupid I am when I read messages about CLOS.
The two choices must be some ordering depending on the textual order
within a DEFCLASS and on the CPL for inherited slots, or else it is
an error to depend on it.
-rpg-
∂08-Jun-87 1907 Bobrow.pa@Xerox.COM Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jun 87 19:07:03 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JUN 87 18:38:46 PDT
Date: 8 Jun 87 18:38 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Open Issues in 87-002
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870608-183846-1250@Xerox>
I was reading over the spec the last few days, and have found the
following open issues that need to be resolved (or issues that I would
like to open). Comments please.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class? Gregor,
what is the answer in PCL right now?
p1-13 What is the initial class hierarchy in CLOS? I recall a message
by Sonya implying she was working on capturing our agreement at Ricky's.
Is there a rewritten section on this?
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
p1-24 Sshould we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
p1-20 Reference to type system correspondence to class system.
------
p2-3 Functions underlying the commonly used macros is neither complete
nor correct. The generic-functions add-method, get-method,
get-setf-generic-function, and remove-method should be in the
metaobjects chapter. make-method (p45)and make-generic-function (p42)
should be removed as soon as we have the initialization protocol set.
p2-6 I think we have reached agreement on the extension to
call-next-method to take arguments. Do I hear a volunteer to write up
this page.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Comments?
p2-16 We have agreed that we don't yet know whether the :constructor
option should be part of defclass.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here "returns the name of the class"
p2-22 Same comment as 2-19
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
p2-39 Arguments: "list of t's" should be replaced by "list of classes
named t" since get-method only takes specializers, not names of
specializers.
p2-40 Should be specified that get-setf-generic-function is set-able
(see 1-18
p2-44 INITIALIZATION PROTOCOL for make-instance.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
p2-51 print-object should take a depth argument.
p2-54 slot-missing should be documented
∂09-Jun-87 0719 skeene@STONY-BROOK.SCRC.Symbolics.COM Open Issues in 87-002
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 07:19:39 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168008; Tue 9-Jun-87 10:18:45 EDT
Date: Tue, 9 Jun 87 10:18 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Open Issues in 87-002
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870608-183846-1250@Xerox>
Message-ID: <870609101827.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 8 Jun 87 18:38 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I was reading over the spec the last few days, and have found the
following open issues that need to be resolved (or issues that I would
like to open). Comments please.
p1-13 What is the initial class hierarchy in CLOS? I recall a message
by Sonya implying she was working on capturing our agreement at Ricky's.
Is there a rewritten section on this?
It's almost done. I'll finish it up this week and send it to the list.
∂09-Jun-87 0803 kempf%hplabsc@hplabs.HP.COM I. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:03:35 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:03:22 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:02:18 pdt
Date: Tue, 9 Jun 87 08:02:18 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091502.AA00446@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: I. Formal Specification of Gen. Fcn. Invocation
For some time now, I have been somewhat bothered by the lack of
precision in the 87-002 specification of method invocation. While
the rest of the document (particularly the inheritance algorithm)
is fairly precisely worded, the section of Part 1 on method combination
and calculation of the effective method is fairly loose and informal.
Until recently, I've been involved in getting an attractively performing
prototype of CLOS up for our internal applications developers, and
so have not had any time to look at the issue in any detail. However,
having reached a checkpoint in that effort, I decided to revisit the
issue and attempt a formal specification of method invocation and
combination.
I will post the results in a series of three notes which deal with
the three aspects of calculating the effective method:
1) Determining the set of applicable methods,
2) Sorting the set of applicable methods by precedence order,
3) Calculating the effective method from the sorted set of
applicable methods.
I would hope that one of the committee members with interest and
inclination would check through the specification and offer any
corrections or additions, and that the 87-002 document could be
amended to include the result. If amending the document turns out
to be not possible, perhaps some other medium could be found for
presenting the result.
As an "executive summary", here is a short overview of the result:
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
requires that CALL-NEXT-METHOD in the least specific :AROUND method
behave fundamentally differently than in other instances. It also
contradicts the statement in the middle of the page that the
most specific :AROUND method provides the value for the invocation.
I suspect it is a typo, and would suggest that the statement in
the middle of the page prevail.
2) The case of having two EQL specializers on the same parameter
which differ during sorting of applicable methods cannot occur.
It is forbidden by the way in which the set of applicable methods
is constructed. An ambiguous statement in the second paragraph at
the top of pg. 1-22 implies that it can, however.
3) The least formal aspect of this specification is Part 3).
I think that some form of temporal logic would be needed to
do this correctly (I may be wrong, however), and so, rather
than go to that machinery, I simply made some general observations
and reasoned somewhat informally. Ultimately, it might be worth
doing the exercise.
Walter Olthoff, in our lab, has done some preliminary work to
cast the specification into the Axis executable formal specification
language, and we may continue this effort as an additional check
on accuracy.
I've also made some initial notes on an application of how this
specification could be used (for anyone who thinks its a waste
of time). In particular, it is possible to derive conditions on
the actual parameters which limit changes in the set of applicable
methods, changes in the sorted list of applicable methods, or both,
it arguments are allowed for CALL-NEXT-METHOD. These conditions
may be useful in construction compile time optimizations, for example.
Finally, the restriction to standard character sets has required
the use of bizarre (for formal methods) notation. For this, I
apologize. One of these days e-mail will support enough bandwith
that we can send around bitmaps.
jak
∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM II. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:03:59 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:03:55 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:02:47 pdt
Date: Tue, 9 Jun 87 08:02:47 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091502.AA00451@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: II. Formal Specification of Gen. Fcn. Invocation
Formation of the Set of Applicable Methods
Given, a generic function invocation:
(gf a(1) a(2) a(3) ... a(n) )
where:
gf = generic function name
a(j) = jth actual parameter
Let:
A = { a(j) }, j=1 ... n
M = { m(i) | m(i) is a method function for gf}
m = number of required parameters for gf
We seek to form the set of applicable methods, MA. The 87-002
wording about how this is done is rather vague:
Given a generic function and a set of arguments, the
applicable methods are all methods for that generic
function whose parameter specializers are satisfied
by their corresponding arguments.
A suggested rewording, which would tighten up the specification
is:
Given a generic function invocation, the applicable
methods are all methods all of whose formal parameter
specializers satisfy Relationship R with respect to
the corresponding actual parameters.
We now define Relationship R.
Let:
F(i)={ f(j) | f(j) is a formal parameter specializer for m(i) }
1 <= j <= m
Note that the F(i) are ordered sets, whose elements match one for one
with the elements of A. In cases where there are more required parameters
than specialized parameters, we extend F(i) using T as the specializer,
indicating that any actual parameter will match the formal parameter
specializer.
Define c(j) as the class of actual parameter a(j). With apologies
to Knuth, define Algorithm I as the algorithm used to calculate
the class precedence list for c(j), and cpl(j) as the result of
applying Algorithm I to c(j). Since the class precedence list is
a totally ordered set, we can define the index operator to return
the index of c(l) in the class precedence list:
index: class-object x cpl -> nat* (* is needed for error case)
This operation will be needed during sorting.
The following predicates map elements of f(j) into booleans:
eql-specializer-p = true if f(j) is a quoted object
false otherwise
class-specializer-p = true if f(j) is a class object
false otherwise
Relationship R is satisfied for one of the F(i) if and ony if, for
all (f(j), a(j) ), j = 1 ... n, either:
eql-specializer-p(f(j)) AND a(j) = f(j)
OR
class-specializer-p(f(j)) AND f(j) element cpl(j)
We denote the set of applicable methods as MA, and go on to
specifying the sorting algorithm.
jak
∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM III. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:04:29 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:04:28 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:03:24 pdt
Date: Tue, 9 Jun 87 08:03:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091503.AA00467@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: III. Formal Specification of Gen. Fcn. Invocation
Sorting the Set of Applicable Methods
Let:
MA = { ma(i) | ma(i) is an applicable method }
F(i) = { f(j) | f(j) is a formal parameter specializer for ma(i) }
Define the predicate
class-equal-p: class-object x class-object -> boolean
as:
class-equalp(f(l),f(m)) = true if f(l) and f(m) represent
the "same" class
false otherwise
We assume that the F(i) are totally ordered, with the ordering determined
by the :ARGUMENT-PRECEDENCE-ORDER for the generic function (default
being left to right).
Taking the F(i) pairwise, we define the equivalence relationship
"qualifier equal" (denoted =(q) ) on the corresponding ma(i)
as follows.
Let f(i,k) and f(j,k) be the kth elements from F(i) and F(j), respectively.
Then ma(i) =(q) ma(j) if and only if:
( eql-specializer-p(f(i,k)) AND eql-specializer-p(f(j,k))
AND f(i,k) = f(j,k)
)
OR
( class-specializer-p(f(i,k)) AND class-specializer-p(f(j,k))
AND class-equal-p(f(i,k),f(j,k))
)
for all (f(i,k),f(j,k)), k = 1 ... n
Note that =(q) groups the ma(i) into equivalence classes, with the
members of an equivalence class being distinguishable only by virtue
of their method qualifiers.
Let MAQ be the set of equivalence classes formed by applying =(q)
to MA. We impose a total ordering on MAQ by the following procedure.
For all maq(i), maq(j), i != j, select an ma(i) and ma(j) and
let F(i) and F(j) be the respective sets of ordered formal parameter
specializers.
Since ma(i) and ma(j) are from different equivalence classes,
there will a least k, 1 <= k <= n, for which the f(.,k) are
not equal, with the f(.,k) being ordered with respect to the ordering
imposed by the generic function.
For that k, let cpl(k) be the class precedence list for the
class c(k) of the matching formal parameter a(k). Define the
following predicate:
cpl-precedes-p: class-object x class-object x cpl -> boolean
as:
cpl-precedes-p(c(l),c(m),cpl) = true if index(c(l),cpl) <=
index(c(m),cpl)
false otherwise
We say that maq(i) is more specific than maq(j)
(written maq(i) <(p) maq(j) ) if and only if one of the following
is true:
1) eql-specializer-p(f(i,k))
2) class-specializer-p(f(i,k)) AND (NOT (eql-specializer-p(f(j,k)))
AND cpl-precedes-p(f(i,k),f(j,k),cpl(k))
Otherwise maq(j) <(p) maq(i).
Note that we need not even consider the case in which:
eql-specializer(f(i,k)) AND eql-specializer(f(j,k))
since construction of the set of applicable methods assures that
f(i,k) = f(j,k) if this true, in which case ma(i) and ma(j) would
be in the same equivalence class, or would not differ on specializer
k.
We denote the totally ordered set of qualifier equivalence classes
as MAQS and go on to specify the calculation of the effective
method.
jak
∂09-Jun-87 0805 kempf%hplabsc@hplabs.HP.COM IV. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:05:04 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:04:50 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:03:47 pdt
Date: Tue, 9 Jun 87 08:03:47 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091503.AA00472@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: IV. Formal Specification of Gen. Fcn. Invocation
Calculation of the Effective Method
Given the totally ordered set of method equivalence classes, MAQS,
the effective method (what actually gets executed) needs to be
formed.
In the general case, nothing can be said formally about how to
calculate the effective method, because the metaclass function
COMPUTE-EFFECTIVE-METHOD can return any Lisp form, if user
defined method combination is applicable.
We therefore restrict consideration to standard method combination.
We now need to break down the equivalence classes in MAQS and
sort out the methods based on their qualifiers.
From the sorting calculation, we remember that two applicable methods
are qualifier equivalent (written =(q)) if they are the same, except
for their method qualifiers. Applicable methods which are =(q) form
equivalence classes, which are sorted by precedence order, with
the precedence order being designated by <(p).
Define the following predicates:
primary-p: method -> boolean
primary-p(m) = true if m is an unqualified (primary) method
false otherwise
around-p: method -> boolean
around-p(m) = true if m is an :AROUND qualifed method
false otherwise
before-p: method -> boolean
before-p(m) = true if m is a :BEFORE qualified method
false otherwise
after-p: method -> boolean
after-p(m) = true if m is a :AFTER qualified method
false otherwise
Note that restriction to standard method combination means that
the following:
NOT (primary-p(ma(i)) OR around-p(ma(i)) OR before-p(ma(i))
OR after-p(ma(i))
)
cannot occur, for ma(i) element of MA, the set of applicable methods.
Given an ma(i), let the function:
preceedes-p: method x method x sorted-=(q)-set -> boolean
take two methods and the sorted set of =(q) equivalence classes
and return true if the equivalence class of the first argument is
more specific than that of the second.
Form the following four sets:
MR = { ma(i) | ma(i) element MA AND around-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MP = { ma(i) | ma(i) element MA AND primary-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MB = { ma(i) | ma(i) element MA AND before-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MF = { ma(i) | ma(i) element MA AND after-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
Specification of standard method combination requires that the
execution sequence for the four sets be ordered as follows:
MR -> MB -> MP -> MF -> {mr(1) | mr(m), m = cardinality(MR) }
Complete execution of MB and MF is guaranteed, if either MR = {}
or mr(m) calls CALL-NEXT-METHOD, so transferring control to mb(1).
In general, unless the method body is coded otherwise, only mr(1)
need be completely executed. However, mp(1) must exist (even if
it is not executed) or an error occurs. (Aside: was this the
intended behavior? It seems to me that making control transfer
from the :AROUND method to the primary method dependent on
whether or not the user codes the least specific :AROUND method
with a CALL-NEXT-METHOD makes the :AROUND method more like a
primary, in the qualitative sense.)
The end sequence of effective method execution is ambiguously
specified. The middle of pg. 1-24 implies that, given MR exists,
then the return value is determined by mr(1), the most specific
:AROUND method, while the bottom of the page implies that,
given a sequence of execution transfers occurs in which execution
leaves MR through the least specific method (mr(m), m = cardinality(MR)),
then control transfers back to the calling continuation
for the entire generic function invocation, rather than
through return of the CALL-NEXT-METHODs to mr(1). I believe this is a typo.
As a solution, I would suggest that CALL-NEXT-METHOD in mr(m) behave
exactly the same as in other cases. The "next" method in this case
would be one of mb(1) (the first :BEFORE method) or mp(1) (the first
primary), depending on whether or not MB = {} (i.e., if there are
any :BEFORE methods). When CALL-NEXT-METHOD returns, control returns
to mr(m-1), and, eventually, to mr(1), which then controls the return
value.
In any event, control transfer from MR to MB can occur only via
a CALL-NEXT-METHOD in mr(m). Once control transfer to MB has occured,
MB is fully executed, then (at least) mp(1) and any other mp(j) via
CALL-NEXT-METHOD. After execution of the MP, MF is fully executed,
and control returns to mp(m). Depending on whether you believe
the middle or bottom of 1-24, mp(m) either returns the primary
value directly to the generic function calling continuation,
or the CALL-NEXT-METHOD in mp(m) returns the value
to its continuation, etc., until mp(1) is reached,
where the value is returned to the gf's continuation.
Additional rules on pg. 1-25 spell out where CALL-NEXT-METHOD can
be used, and the logic behind standard method combination.
jak
∂09-Jun-87 0854 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:54:10 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:53:45 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:52:15 pdt
Date: Tue, 9 Jun 87 08:52:15 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091552.AA01177@hplabsc>
To: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Subject: Re: Order of Initialization
>Jak sez:
>
>``This says nothing, however, about the order in which the initialization
>forms for all the slots are run.''
>
>I respond:
>
>This say everything about how stupid I am when I read messages about CLOS.
>
It's difficult to maintain continuity in a discussion when the lag in
a reply is a day. Not your fault.
>The two choices must be some ordering depending on the textual order
>within a DEFCLASS and on the CPL for inherited slots, or else it is
>an error to depend on it.
>
>
As I see it, Common Lisp does one of three things when the order of
evaluation matters:
1) Specifies the order, as is the case with the order of evaluation
of function arguments, or PROGN,
2) Gives the programmer a construct in which the order is specified
and one in which it is not, as in LET and LET*.
3) Does not specify in what order evaluation occurs. DEFSTRUCT is
in this category (except for the statement that initialization
forms are evaluated in the lexical context of the DEFSTRUCT
definition). This would leave it up to the implementation.
I think 1) should be the case. This avoids making it implementation
dependent (case 3) and avoids having to introduce extra syntatic
machinery (case 2).
jak
∂09-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 09:33:42 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 09:33:41 pdt
Received: by hplabsc ; Tue, 9 Jun 87 09:32:24 pdt
Date: Tue, 9 Jun 87 09:32:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091632.AA02166@hplabsc>
To: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Open Issues in 87-002
Some opinions on the open issues note which Danny posted.
>p1-12 Should defclass be allowed to change the metaclass of an existing
>class?
I think DEFCLASS shouldn't be allowed to change the metaclass, since
the representation for instances of classes with the two different
metaclasses might be radically different.
>p1-17 "It is currently under discussion whether to provide constructs
>for giving generic functions local names." Do we want to have this
>discussion, or to punt on this syntax. I recall we did come up with some
>reasonble semantics for a GFLET and GFLABELS.
There have been a couple times when I've thought this would be handy.
On the other hand, we may ultimately be accused of junking up the
standard with things that some people don't need. On the presumption
that someone will accuse us of that anyway, it would probably be a good idea
to look into this. I believe there was some discussion of a GLAMBDA
in addition? Perhaps this functionality could be achieved by providing
a GFUNCTION special form (like the FUNCTION special form), which takes
a list of lambda expressions and produces a generic function object.
I suppose we'll need a reader macro for this as well, like #'.
Arguments for these constructs are that it integrates generic functions
more smoothly into the language. Arguments against are that generic
functions are a higher level modularity mechanism than functions. My
opinion is that the former is probably more relevant, since the package
system is really the fundamental modularity mechanism for organizing
medium scale structure in Common Lisp.
>p1-18 It is not specified whether get-setf-generic-function is a
>setf-able form. I suggest that it be made so. This would allow one to
>trace setf-generic-function's without having to know their names.
I vote yes on this one. We are already having trouble tracing
SETF- generic functions, and need some kind of handle.
>p1-24 Sshould we have a call-next-method? which calls such a next method
>if it exists, else returns nil (rather than signalling an error?). This
>seems useful rather than having to define many base methods on object.
I think this would be a good idea, however, we need to consider the
performance tradeoff. If CALL-NEXT-METHOD is viewed as a means of
modifying the flow of control in the effective method, rather than
a fast way of invoking the next least specific method, I think this
would be useful (although a compiler would be free to optimize, if
it so chooses). In the most general case, the conditions determining
whether the set of applicable methods are still valid would need
to be re-checked on each invocation of CALL-NEXT-METHOD with parameters.
>p2-3 Functions underlying the commonly used macros is neither complete
>nor correct. The generic-functions add-method, get-method,
>get-setf-generic-function, and remove-method should be in the
>metaobjects chapter. make-method (p45)and make-generic-function (p42)
>should be removed as soon as we have the initialization protocol set.
Yes. Do people feel the initialization issues are well enough
understood that a proposed addition can be generated in Boston?
>p2-6 I think we have reached agreement on the extension to
>call-next-method to take arguments. Do I hear a volunteer to write up
>this page.
I'll do it, if nobody objects. I won't be able to do it by Boston,
however.
>2-13(?) The generic function class-name is not written up. It returns a
>name for the class as argument. I believe that (class-name class)
>should be setf-able. Can a class have more than one name? Should
>class-name then return a second argument -- the rest of the names this
>class is known by.
I think the class name should be changable, I don't think it should
have more than one name (at least, not for the default metaclass).
But I'm open to hearing some discussion on it, if anybody has any
ideas why it should be done.
>p2-19 Values: I thought we agreed that all top level forms should return
>the object. It says here "returns the name of the class"
This sounds like a typo. It should return the class object.
>p2-22 Same comment as 2-19
Ibid.
>p2-26 I believe that short form method combination ought to be a macro
>in the standard library, and documented there, not in the basic
>principles. I think the standard combinations :append, :and, :or, ...
>should also be put in the standard library too.
I agree.
>p2-35 The argument order of the setf method ought to be documented here.
>Gregor proposed that new-value be the first argument. Any problem with
>this?
I've gotten some complaints from my users that they would rather see
it as the second argument, and also the second argument to the
SETF- generic function. Personally, I don't particularly care, but
I thought I'd just pass this along.
>p2-44 INITIALIZATION PROTOCOL for make-instance.
Yes, this needs to be resolved.
>p2-51 print-object should take a depth argument.
Yes, this is needed. I think we need to maintain some compatibility
with DEFSTRUCT on this.
∂09-Jun-87 1008 kahn.pa@Xerox.COM Re: Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:08:17 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 JUN 87 10:07:51 PDT
Date: Tue, 9 Jun 87 10:07:35 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
Subject: Re: Open Issues in 87-002
In-Reply-To: <870608-183846-1250@Xerox>
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870609-100751-1086@Xerox>
> p1-18 It is not specified whether get-setf-generic-function is a
setf-able
> form. I suggest that it be made so. This would allow one to trace
setf-generic-function's
> without having to know their names.
Maybe I'm confused, but how would it help tracing unless one re-compiled
all the setf's using the generic function? And how is the problem of
tracing setf's in CLOS any different than the general Common Lisp
problem?
References
Bobrow's message of Mon, 8 Jun 87 18:38:00 PDT -- Open Issues in 87-002
∂09-Jun-87 1035 Bobrow.pa@Xerox.COM Re: Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:35:13 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 10:33:13 PDT
Date: 9 Jun 87 10:33 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Open Issues in 87-002
In-reply-to: Ken Kahn <Kahn.pa>'s message of Tue, 9 Jun 87 10:07:35 PDT
To: Kahn.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870609-103313-1143@Xerox>
>p1-18 It is not specified whether get-setf-generic-function
>is a setf-able form. I suggest that it be made so. This would
>allow one to trace setf-generic-function's without having to
>know their names.
Maybe I'm confused, but how would it help tracing unless one
re-compiled all the setf's using the generic function? And how is
the problem of tracing setf's in CLOS any different than the
general Common Lisp problem?
This is the same problem as tracing setf's of functions in CommonLisp.
But we have no two argument defsetf. Will someone who knows tell us how
that is done in some Common Lisps.
danny
∂09-Jun-87 1050 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:48:58 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 10:48:36 pdt
Received: by hplabsc ; Tue, 9 Jun 87 10:47:25 pdt
Date: Tue, 9 Jun 87 10:47:25 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091747.AA03141@hplabsc>
To: Bobrow.pa@Xerox.COM, Kahn.pa@Xerox.COM
Subject: Re: Open Issues in 87-002
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Here's how I do it:
(macroexpand '(setf <form> b))
then take whatever the name is from the macroexpansion. Turns out
that the names for things like SVREF are mostly well behaved
(LISP::SETF-SVREF) so I can guess most of the time in our Lisp.
This may be an issue for the cleanup committee (perhaps they are
already looking at it?).
jak
∂09-Jun-87 1104 Bobrow.pa@Xerox.COM Re: Order of Initialization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 11:03:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 10:55:03 PDT
Date: 9 Jun 87 10:54 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Order of Initialization
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue, 9
Jun 87 08:52:15 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Message-ID: <870609-105503-1199@Xerox>
jak says
As I see it, Common Lisp does one of three things when the
order of evaluation matters:
1) Specifies the order, as is the case with the order of
evaluation of function arguments, or PROGN,
2) Gives the programmer a construct in which the order is
specified and one in which it is not, as in LET and LET*.
3) Does not specify in what order evaluation occurs. DEFSTRUCT
is in this category (except for the statement that initialization
forms are evaluated in the lexical context of the DEFSTRUCT
definition). This would leave it up to the implementation.
I think 1) should be the case. This avoids making it
implementation dependent (case 3) and avoids having to introduce
extra syntatic machinery (case 2).
I think one should not depend on the order. Consider the ambiguity
resulting from two class definitions:
(defclass c1 ()
((x :initform (initx1))
(y :initform (inity))))
(declass c2 (c1)
((x :initform (initx2)))
These can be in a file in either order. Which order for eveluation of
(initx2) and (inity) do you think is correct. I can think of arguments
for both. Further, consider
(defclass c3 (c1)
((z :initform (initz))
(y :initform (inity2))
(x :initform (initx3))))
So my choice is 3, the user should not depend on the order.
danny
∂09-Jun-87 1136 Bobrow.pa@Xerox.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 11:36:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 11:35:01 PDT
Date: 9 Jun 87 11:34 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue, 9
Jun 87 08:02:18 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870609-113501-1274@Xerox>
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
requires that CALL-NEXT-METHOD in the least specific :AROUND method
behave fundamentally differently than in other instances. It also
contradicts the statement in the middle of the page that the most
specific :AROUND method provides the value for the invocation. I
suspect it is a typo, and would suggest that the statement in the
middle of the page prevail.
You must have a different reading of the words than I do. In the middle
of the page it says:
* If there are any :around methods, the most specific :around method is
called. It supplies the value for the method.
At the bottom it uses the phrase "If no :around methods were invoked"
This means that there are no :around methods. In this case, the value
is the value returned from what I will call the "effective primary
method" which will be the value returned by the most specific primary
method. The "effective primary method" is the method constructed
approximately as
(PROG2 (PROGN before1 .. beforen) primary1 (PROGN aftern ... after1))
where index 1 is more specific method than one with 2, ...
call-next-method always works on a list of effective methods, and always
calls the next in the list. The list for standard method combination is
(around1 ... aroundn effective-primary-method)
and hence there is no difference in what call-next-method does in the
two cases. The value is of course the value of the first method on this
list. I am not sure I understand your statement:
" the invocation of CALL-NEXT-METHOD in the least specific
:AROUND method would return the effective method invocation result
to the continuation (caller)"
Further in your formal description, you talk about control passing to
the before methods, without building a construct like
effective-primary-method. I think this is a mistake, since it loses the
nesting of the methods, and how values are returned.
-----
2) The case of having two EQL specializers on the same
parameter which differ during sorting of applicable methods cannot
occur.
I read the statement on page 1-22 as a proof of this statement.
∂09-Jun-87 1743 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 9 Jun 87 17:43:30 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ac03830; 9 Jun 87 20:24 EDT
Received: from ti-csl by RELAY.CS.NET id ag02593; 9 Jun 87 20:18 EDT
Received: by tilde id AA10877; Tue, 9 Jun 87 16:47:43 CDT
Message-Id: <2759261775-6137078@Jenner>
Date: Tue, 9 Jun 87 16:36:15 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Bobrow.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
In-Reply-To: Msg of 2 Jun 87 18:37 PDT from Bobrow.pa@xerox.com
My message has two parts, the first one is about specifics and the
second one is about the general instance creation problem.
Part I:
I am trying to comment on the Gregor/Bobrow proposal as I see it after pasting
all the parts together:
from Bobrow:
(defmethod make-instance ((c standard-class) &rest initargs)
(let ((o (allocate-instance c)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o)
This is not enough, we need to be able to pass initargs to allocate-instance as
well.
Thus I think I would rewrite this (using Gregor's part):
(defmethod make-instance ((c standard-class) &rest initargs)
(let* ((init-args (merge-initargs initargs (default-initargs c)))
(o (apply #'allocate-instance c init-args)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o))
Is this correct?
Now, who checks the legality of init-args? It seems it would be merge-initargs.
One thing I am not thrilled about with this proposal is that the legality check,
the defaulting and the merging of the initargs are done in three places. Here
is an example of what I don't like:
If a user wants to explicity override some initargs provided by a
superclass they can do that since everything is procedural and under
their control:
(defmethod class-legal-initargs ((class boat))
(let ((supers (call-next-method)))
(list* ':speed (remove :color supers))))
Now, if default-initargs is left to its usual form, it gets out of sync. We can
produce a default-init-args plist that would contain non legal initargs.
Part II:
Thinking about instance creation, it seems that we have a three
dimensional problem and we try to solve it using two dimensional
projections:
The first dimension is the class hierarchy.
The second is the initargs dimension.
the third is the operations dimension (legality check, defaulting,
side-effect).
Bobrow/Gregor tries to project the problem along the operation dimension,
thus losing the ability to do all the operations at the same place.
Dick tries to project the problem along the initargs dimension, losing
the ability to do legality check simply( which requires a global view
of the initargs).
The basic CLOS generic function mechanism is inherently two dimensional.
We have the class hierarchy dimension and the generic function dimension.
It seems normal that we run into problems if we try to use CLOS generic
function mechanism to model a three dimensional problem.
An ad-hoc solution like moon's can ignore such constraints and can do a
better job at preserving locality and modularity.
My opinion is that we should try to go back to an ad-hoc solution, maybe
as streamlined as it needs to make everybody comfortable with, instead
of trying to force fit instance creation into generic function calling
and adding few macros on top of it.
Patrick.
∂09-Jun-87 1819 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:18:47 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168871; Tue 9-Jun-87 21:16:13 EDT
Date: Tue, 9 Jun 87 21:16 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: SETF- method names
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706041702.AA04950@hplabsc>
Message-ID: <870609211606.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference.
The intent was that they would not have names at all, if I remember
correctly.
However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
You seem to be assuming that for any setf generic function, there will
be some symbol such that SYMBOL-FUNCTION of that symbol yields the setf
generic function. I don't see why. The Symbolics and TI
implementations, to take two examples, do not have any such symbols.
In addition, CLOS has some support for anonymous generic functions,
and presumably setf generic functions would be just one example of
such anonymous generic functions. I don't know how this was intended
to fit into TRACE and other debugging aids.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
If we're going to standardize on a way to name setf generic functions,
it should be a way to name methods as well. After all, you'd like to be
able to trace methods. I firmly believe that it should be based on the
"function spec" system used by Symbolics and TI, not on some scheme of
symbols with generated names. However in the past whenever I have
proposed "function specs" to the Common Lisp community, I got a lot of
abuse, so I'm tired of bothering.
∂09-Jun-87 1832 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:32:35 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168878; Tue 9-Jun-87 21:31:51 EDT
Date: Tue, 9 Jun 87 21:31 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 2 Jun 87 13:29 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870609213148.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Jun 87 1029 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I assumed that a generic function was a function and so could appear in
a function cell. Doesn't the Concepts chapter state that
(typep <generic function> 'function) => T
I presume that a generic function is a function under the cleaned-up
definition.
This is all true, but I think the actual issue was something else. It's
starting to come back to me: it's separating what the SYMBOL-FUNCTION
function does from what the implementation actually stores, so no one
can object on efficiency grounds. This is more of an implementation
note than a language specification.
Moon, do you know the date of your message discussing the non-keyword &key
arguments? What are the considerations?
I don't know the date, but the proposal name was KEYWORD-ARGUMENT-NAME-PACKAGE.
I'll send you the newest copy of it that I have, under separate cover (and
just to Dick).
∂09-Jun-87 1852 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:52:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168882; Tue 9-Jun-87 21:52:18 EDT
Date: Tue, 9 Jun 87 21:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: SETF- method names
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706041702.AA04950@hplabsc>
Supersedes: <870609211606.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Comments: Added comment about tracing functions rather than tracing function-names.
Message-ID: <870609215209.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference.
The intent was that they would not have names at all, if I remember
correctly.
However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
You seem to be assuming that for any setf generic function, there will
be some symbol such that SYMBOL-FUNCTION of that symbol yields the setf
generic function. I don't see why. The Symbolics and TI
implementations, to take two examples, do not have any such symbols.
In addition, CLOS has some support for anonymous generic functions,
and presumably setf generic functions would be just one example of
such anonymous generic functions. I don't know how this was intended
to fit into TRACE and other debugging aids.
CLtL's discussion of TRACE is very vague, so maybe the following doesn't
belong in the standard anyway. But is there any reason why TRACE
couldn't accept functions as arguments, rather than only accepting
function names? The main limitation seems to be that TRACE is a macro
and doesn't evaluate its subforms.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
If we're going to standardize on a way to name setf generic functions,
it should be a way to name methods as well. After all, you'd like to be
able to trace methods. I firmly believe that it should be based on the
"function spec" system used by Symbolics and TI, not on some scheme of
symbols with generated names. However in the past whenever I have
proposed "function specs" to the Common Lisp community, I got a lot of
abuse, so I'm tired of bothering.
∂09-Jun-87 1921 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 19:21:37 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168903; Tue 9-Jun-87 22:21:01 EDT
Date: Tue, 9 Jun 87 22:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870602003210.7.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 2 Jun 87 13:29 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<870602-114805-4200@Xerox>,
<8706022335.AA00365@hplabsc>,
<870603-113213-2135@Xerox>,
<8706032153.AA14903@hplabsc>,
<870605-234940-2970@Xerox>
Message-ID: <870609222055.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Thanks for all the input. This is the summary I came up with:
This file is a list of things that the CLOS committee would like to see
cleaned up. I have tried to keep it brief. Where proposals have been
submitted to the Cleanup committee, the proposal name is listed as
"PROPOSAL: name". Where the Cleanup committee has assigned an issue
name, but there is no proposal yet, it is listed as "ISSUE: name".
1. PROPOSAL: FUNCTION-TYPE
Making FUNCTION be a genuine type (distinct from CONS).
2. PROPOSAL: KEYWORD-ARGUMENT-NAME-PACKAGE
Allowing keyword argument indicators to be non-keyword symbols.
3. ISSUE: DEFSTRUCT-CLOS
A recommendation to design a DEFRECORD facility to replace the part
of DEFSTRUCT that is not replaced by DEFCLASS.
4. ISSUE: PATHNAME-HASH-TABLE-TYPE-DISTINCT
Mandating a bunch of types (I don't have the complete list right now)
to be disjoint from a bunch of other types (again I don't have a
complete list right now) so that they can all be made into classes
without establishing any implementation-dependent subclass relationships.
5. PROPOSAL: SHARP-COMMA-SPECIAL-FORM
(in some Cleanup documents this is called LOAD-TIME-EVAL)
A macro should be able to include in its expansion the same sort
of thing that the #, reader-macro produces, enabling load-time
evaluation.
6. ISSUE: LEXICAL-ENVIRONMENT-ACCESSORS
Providing constructors and accessors for lexical environments.
This is somehow related to or a substitute for a symbol macro
facility [I don't understand the connection --Moon]
7. (no issue name)
Implementation note: clarify that the value returned by SYMBOL-FUNCTION,
and the value accepted by SETF of SYMBOL-FUNCTION, are not necessarily
what the implementation actually stores for purposes of function calling.
Specifically, (SETF (SYMBOL-FUNCTION x) gf), where gf is a generic function,
might create compiled code for method dispatching and store it in a place
associated with x, so that a call to x will compile as a call to that
compiled code, and will never touch the generic function object. However,
even if an implementation uses this technique, (SYMBOL-FUNCTION x) must
return the value gf, not the internal compiled code. Furthermore,
(FUNCALL gf ...) must produce the correct effect; it is permissible for
it to be slower than calling the internal compiled code.
8. (no issue name)
Require (deftype quote (object) `(member ,object)) to be built-in.
9. (no issue name)
Class objects must be acceptable to TYPEP and SUBTYPEP as type-specifiers.
This is probably part of CLOS rather than anything for the Cleanup committee.
∂09-Jun-87 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM I. Formal Specification of Gen. Fcn. Invocation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 20:44:17 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168962; Tue 9-Jun-87 23:43:37 EDT
Date: Tue, 9 Jun 87 23:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: I. Formal Specification of Gen. Fcn. Invocation
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706091502.AA00446@hplabsc>
Message-ID: <870609234334.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 9 Jun 87 08:02:18 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
....I will post the results in a series of three notes which deal with
the three aspects of calculating the effective method....
I found that I was unable to comprehend any of this. I'll try again
some time when I have several hours available and no distractions.
I'm sure that the language in the document could be clearer and
less ambiguous, especially if it wasn't written by a committee, but
right now I'm not sure whether a more formal approach would make the
document easier to understand or would simply obfuscate it and end
up making errors more difficult to uncover.
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
I am unable to find any such requirement. All I see is that the value
returned by the invocation of CALL-NEXT-METHOD in the least specific
:AROUND method is controlled by the most specific primary method.
Are you looking at an old version of the document perhaps?
2) The case of having two EQL specializers on the same parameter
which differ during sorting of applicable methods cannot occur.
It is forbidden by the way in which the set of applicable methods
is constructed. An ambiguous statement in the second paragraph at
the top of pg. 1-22 implies that it can, however.
This typo ("quoted" for "equal") was corrected in the corrections
handed out in March.
∂09-Jun-87 2234 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 22:34:10 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 22:32:55 pdt
Received: by hplabsc ; Tue, 9 Jun 87 22:31:45 pdt
Date: Tue, 9 Jun 87 22:31:45 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706100531.AA10636@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: SETF- method names
Cc: common-lisp-object-system@sail.stanford.edu
>If we're going to standardize on a way to name setf generic functions,
>it should be a way to name methods as well. After all, you'd like to be
>able to trace methods. I firmly believe that it should be based on the
>"function spec" system used by Symbolics and TI, not on some scheme of
>symbols with generated names. However in the past whenever I have
>proposed "function specs" to the Common Lisp community, I got a lot of
>abuse, so I'm tired of bothering.
>
Not being familiar with "function specs", I'm not in a position to
comment on them; however, I think the current situation is pretty
tenuous. As mentioned in the "Open Issues" note and subsequent
discussion, the way I usually trace SETF- functions is by macroexpanding
a form to see what the function name is. Admittedly, one could argue
this is an environmental thing, but since CLtL specifies the TRACE
function, there should be some means of doing this. Tracing methods
would also be nice. Maybe it would be best to defer this for the
moment, since it seems to be a more general problem of SETF-, and
can be solved in PCLOS/PCL (kludgily) by simply generating a more
tractable name, thus keeping my users happy.
jak
∂09-Jun-87 2349 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 23:49:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 23:48:32 PDT
Date: 9 Jun 87 23:48 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 9 Jun 87 22:20 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870609-234832-2213@Xerox>
I'll assign a random proposal name if you like:
8) ISSUE: TYPE-MEMBER-SINGLETON (issue is that (member t) is awkward
when there's only one)
Proposal TYPE-MEMBER-SINGLETON:QUOTE
As you say, point 7 (SYMBOL-FUNCTION may not be what's stored) is
really an implementation note rather than any language specification
change. I don't see that it requires a cleanup, for that reason.
I agree that your point 9 (TYPEP takes class object) really is more part
of the CLOS than a cleanup, (Without CLOS, there are no class objects,
and the issue is moot.)
∂10-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Jun 87 09:33:46 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 10 Jun 87 09:32:47 pdt
Received: by hplabsc ; Wed, 10 Jun 87 09:31:14 pdt
Date: Wed, 10 Jun 87 09:31:14 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706101631.AA15389@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
Cc: kempf%hplabsc@hplabs.HP.COM
Comments from Dave Moon:
>I'm sure that the language in the document could be clearer and
>less ambiguous, especially if it wasn't written by a committee, but
>right now I'm not sure whether a more formal approach would make the
>document easier to understand or would simply obfuscate it and end
>up making errors more difficult to uncover.
Yes, a more formal approach may make the spec require more effort to follow.
What I hoped to avoid is a case like some Common Lisp implementations,
where an implementor picks up on one or two ambiguous phrases, interprets them
in a way which the majority of the implementers interpreted differently,
and thereby makes portablility of application code a lot harder to
achieve. Additionally, with a more formal approach, I think we may have
a better chance at convincing the ISO Committee at looking favorably
on CLOS semantics (even if they don't like the syntax), and perhaps the
Scheme community as well. As far as the object subcommittee's work goes, if
the consensus is that just now is not the time to introduce more
formalism, we can defer discussion until later. I'm planning on pursuing
the problem, since I think it is an interesting and important one, but
I'll avoid posting the details and only post questions or suggested
corrections, if people prefer.
>Are you looking at an old version of the document perhaps?
I have the version which was distributed at the March ANSI meeting,
along with the corrections distributed at the same meeting. If
the on-line version on SAIL or PARCVAX has corrections beyond
those, then I need to take a look at them. We have troubles
getting FTP connections here.
Danny Bobrow's comments:
> 2) The case of having two EQL specializers on the same
> parameter which differ during sorting of applicable methods cannot
> occur.
>I read the statement on page 1-22 as a proof of this statement.
The problem is the following. On page 1-21, last paragraph, there
is a description of the sorting process:
Compare the corresponding parameter specializers. When
a pair of parameter specializers are equal, proceed to
the next pair and compare them for equality. If all
corresponding parameter specializers are equal, the two
methods must have different qualifiers; in this case, either
method can be selected to precede the other (Comment:
this is also not strictly true, since they will actually
be in the same equivalence class. One could be a :BEFORE
and the other a :AFTER method, for example. In fact,
the two methods are incomparable with regard to precedence.)
If not all corresponding parameter specializers are equal,
the first pair of parameter specializers that are not
equal determines the precedence.
At this point, we move to pg. 1-22, and I'm assuming the rest
of the section deals with how to determine precedence. Determining
precedence for class specifiers is in the next paragraph, then the second last
paragraph in the section discusses EQL precedence:
If just one parameter is (QUOTE <object>), the method
with that parameter specializer preceeds the other
method. (Comment: Here comes the condition which cannot
occur.) If both parameter specializers are quoted
objects, the specializers must be quoted objects
(otherwise the two methods would not both have been
applicable for this argument).
In fact, at this point, it is not possible for both parameter
specializers to be quoted objects, because, if a specializer is
a quoted object, it must be EQL to the actual parameter for
the method, to even be an applicable method. If it is EQL to
the actual parameter, then two methods cannot differ on that
specializer, because all methods with an EQL specializer at
that parameter position will have the same specializer.
> 1) Only one major inconsistency was found in the specification.
> The requirement at the bottom of pg. 1-24 that the invocation of
> CALL-NEXT-METHOD in the least specific :AROUND method would return
> the effective method invocation result to the continuation (caller)
> requires that CALL-NEXT-METHOD in the least specific :AROUND method
> behave fundamentally differently than in other instances. It also
> contradicts the statement in the middle of the page that the most
> specific :AROUND method provides the value for the invocation. I
> suspect it is a typo, and would suggest that the statement in the
> middle of the page prevail.
>
>You must have a different reading of the words than I do. In the middle
>of the page it says:
>* If there are any :around methods, the most specific :around method is
>called. It supplies the value for the method.
>
>At the bottom it uses the phrase "If no :around methods were invoked"
>This means that there are no :around methods. In this case, the value
>is the value returned from what I will call the "effective primary
>method" which will be the value returned by the most specific primary
>method.
I'm not arguing with the case of no :AROUND methods, but rather
with the case of a CALL-NEXT-METHOD in the least specific :AROUND
method which causes control transfer to the effective primary
method. The statement in my copy of the spec says:
Otherwise, the value or values returned by the most
specific primary method are those returned by the invocation
of CALL-NEXT-METHOD in the least specific :AROUND
method.
My reading was that the following sequence of events occurs:
generic function invocation context:
most specific :AROUND
CALL-NEXT-METHOD -----------> to next most specific
next most specific :AROUND
CALL-NEXT-METHOD------------> to next next most specific
....
in least specific :AROUND:
CALL-NEXT-METHOD -------> transfer of control to
primary method
and execution of it.
Upon completion, transfer
back to least specific
THROW to generic <------- :AROUND method
function invocation
context.
In fact, on a closer reading (and looking at the following comments
about how to construct the effective primary method), I agree
that this interpretation is faulty.
> The "effective primary method" is the method constructed
>approximately as
>(PROG2 (PROGN before1 .. beforen) primary1 (PROGN aftern ... after1))
>where index 1 is more specific method than one with 2, ...
>
>call-next-method always works on a list of effective methods, and always
>calls the next in the list. The list for standard method combination is
>
>(around1 ... aroundn effective-primary-method)
>and hence there is no difference in what call-next-method does in the
>two cases. The value is of course the value of the first method on this
>list. I am not sure I understand your statement:
> " the invocation of CALL-NEXT-METHOD in the least specific
> :AROUND method would return the effective method invocation result
> to the continuation (caller)"
>
My initial reading of the bottom of 1-24 resulted in the interpretation of
the execution sequence as listed above. This is what I meant by
the statement.
>Further in your formal description, you talk about control passing to
>the before methods, without building a construct like
>effective-primary-method. I think this is a mistake, since it loses the
>nesting of the methods, and how values are returned.
I agree. I think the concept of the effective primary method is a
good one and it clarifies the concepts. Additionally, I think my
reading of the bottom of pg. 1-24 was confused by the fact that
I was interpreting the return value of the primary method with the
the return value of the generic function, since the first sentence
of the paragraph deals with the latter, and the second with the
former. It might be helpful to seperate out these two concepts,
in language something like:
The process of generic function invocation is completed
by returning value(s) to the invocation context. If
no :AROUND methods were invoked, then the most specific
primary method supplies the value(s) returned
by the generic function. If the most specific :AROUND
method was invoked, but control transfer to the
effective primary method via CALL-NEXT-METHOD in the
least specific :AROUND method does not occur, then
the return value(s) of the most specific :AROUND method
are the value(s) returned by the generic function. If
control transfer to the effective primary method does
occur, then the value(s) returned by the effective
primary method are potentially modifiable by the
:AROUND methods, and, again, the most specific :AROUND
method supplies the return value(s) for the generic
function invocation.
In the meantime, I'll look into incorporating the idea of an
effective primary method into the formalism.
jak
∂10-Jun-87 1006 RPG CLOS Document
To: common-lisp-object-system@SAIL.STANFORD.EDU
The version of the document on SAIL has the true errata corrected.
-rpg-
∂10-Jun-87 1114 skeene@STONY-BROOK.SCRC.Symbolics.COM Concepts chapter on standard type classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 11:14:14 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169429; Wed 10-Jun-87 14:13:43 EDT
Date: Wed, 10 Jun 87 14:13 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Concepts chapter on standard type classes
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610141334.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Below is a proposed section to go into the Concepts part of the document.
I'll also be sending a draft section to go into the Design Rationale
part of the document.
\beginSection{Integrating Types and Classes}
The \CLOS\ maps the Common Lisp type space into the space of classes.
Every class that has a name has a corresponding type with the same
name. {\bf defclass} and {\bf defstruct} define both types and classes.
The name of every class is a valid type specifier. In addition, every
class object is a valid type specifier. Thus the expression {\tt (typep
{\it object class\/})} evaluates to true if the class of {\it object\/}
is {\it class\/} itself or a subclass of {\it class}. The evaluation of
the expression {\tt (subtypep {\it class1 class2\/})} returns the
values {\bf t t} if {\it class1\/} is a subclass of {\it class2\/} or if they
are the same class; otherwise it returns the values {\bf nil t}.
Many but not all of the predefined Common Lisp type specifiers have a
corresponding class with the same name as the type. For
example, the type {\bf array} has a corresponding class named {\bf array}.
A class that corresponds to a predefined Common Lisp type is called a
{\bit standard type class\/}. Each standard type class has the class
{\bf standard-type-class} as a metaclass. It is not allowed to make an
instance of a standard type class with {\bf make-instance} nor to include
a standard type class as a superclass of a class.
The purpose for specifying that many of the standard Common Lisp types
have a corresponding class is to allow users to write methods that
discriminate on these types. The hierarchical relationships among
the Common Lisp types are maintained by the classes corresponding to
those types. Thus the existing type hierarchy is used for determining
the class precedence lists for each standard type class.
Method selection requires that a class precedence list can be
determined for each class, ordering the class and its superclasses from
most to least specific. In some cases, {\it Common Lisp: the
Language\/} does not specify a subtype/supertype relationship for two
supertypes of a given type. For example, {\bf null} is a subtype of
{\bf symbol} and {\bf list}, but {\it Common Lisp: the Language\/} does
not specify whether {\bf symbol} is more or less specific than {\bf
list}. The \CLOS\ specification defines those relationships for all
standard type classes.
The following table lists the set of standard type classes required by
\CLOS\. The superclasses of each standard type class are presented in
order from most specific to most general:
STANDARD TYPE CLASS SUPERCLASSES
array t
bit-vector vector, array, sequence, t
character t
complex number, t
cons sequence, t
float number, t
integer rational, number, t
list cons, sequence, t
null list, cons, symbol, sequence, t
number t
ratio rational, number, t
rational number, t
sequence t
string vector, array, sequence, t
symbol t
t
vector array, sequence, t
Note that instances of standard classes are type disjoint with all other
types.
Individual implementations can allow other type specifiers to have a
corresponding class. Also individual implementations can add additional
subclass relationships as long as they do not violate {\it Common Lisp:
the Language\/}.
Creating a type by means of {\bf defstruct} also creates a class in the
space of Common Lisp classes. Such a class is an instance of {\bf
structure-class} and a direct subclass of the class that corresponds to
the included structure, if any.
No type specifier that is a list, such as {\tt (vector double-float
100)}, has a corresponding class. No type defined by {\bf deftype} has
a corresponding class.
For a discussion on some of the design decisions underlying this aspect
of \CLOS\, see the section "Design Theories of the Integration of Types
and Classes".
\endSection%{Integrating Types and Classes}
∂10-Jun-87 1117 skeene@STONY-BROOK.SCRC.Symbolics.COM Design Rationale section on standard type classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 11:17:11 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169433; Wed 10-Jun-87 14:16:24 EDT
Date: Wed, 10 Jun 87 14:16 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Design Rationale section on standard type classes
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610141615.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
\beginSection{Design Theories of the Integration of Types and Classes}
This section explains some of the design decisions regarding the
integration of the existing Common Lisp type system with the \CLOS\
class system. For background information, see the section
``Integrating Types and Classes''.
This section answers the following questions:
\beginlist
\item{\bull} Why do some of the standard Common Lisp types have a
corresponding class?
\item{\bull} Why don't all of the standard Common Lisp types have a
corresponding class?
\item{\bull} What were the guidelines for choosing which types would
have a class, and which would not?
\endlist
Question: Why do some of the standard Common Lisp types have a
corresponding class?
The purpose for specifying that many of the standard Common Lisp types
have a corresponding class is to allow users to write methods that
discriminate on these types; this is a powerful programming tool.
The standard type specifiers fit neatly into the method selection
model, but they are not suited to the complete \CLOS\ model, with respect
to building classes from superclasses, creating instances, and changing
the class of an instance. It is useful to discuss the practical and
conceptual distinctions between standard type classes and standard
classes. (A standard class is a user-defined class.) Standard type
classes have the following restrictions:
\beginlist
\item{\bull} A standard type class cannot be used as superclasses.
The difference between standard type classes and standard classes is
in the implementation of instances. Instances of a standard type class
are implemented in a specialized way that does not permit subclassing.
In some implementations some classes documented as standard type classes
might in fact be implemented as standard classes, but portable
programs cannot assume this.
\item{\bull} {\bf make-instance} cannot be used to create an instance
of a standard type class.
The capability of using {\bf make-instance} for standard type classes
gives no extra power or utility to the programmer. Also, the \CLOS\
model does not extend gracefully in this direction. Standard
classes have slots, but standard type classes have values of other
sorts (such as the value of an integer or the elements of an array)
which do not fit the {\bf make-instance} model.
\item{\bull} You cannot change the class of an instance of a standard
type class.
The semantics of changing an instance of a standard type class are not
at all clear. This is a basic difference between standard type
classes and standard classes.
\endlist
Question: Why don't all of the standard Common Lisp types have a
corresponding class?
It would be useful to extend the standard type classes to encompass the
full generality of Common Lisp type specifiers, but this raises
theoretical issues that are not yet appropriate for standardization.
These issues include:
\beginlist
\item{\bull} Deciding what to do when an argument is an instance of two
types, both of which have methods, but neither is a subtype of the
other. Some of the types in {\it Common Lisp: the Language\/}
have no constraints on their precedence relations to other types.
\item{\bull} The types that specify subranges present similar problems.
It is unclear how to determine the relative precedence of two
subranges of the same type.
\item{\bull} Dealing with Boolean combinations, such as negation, {\bf
and}, and {\bf or} presents problems with determinging relative
precedence order. For more information, see ``Boolean Classes'' by D.
McAllester and R. Zabih, a paper presented at the 1986 ACM First Annual
Conference on Object-Oriented Programming Systems, Languages, and
Applications.
\item{\bull} Some Common Lisp type specifiers are not defined clearly
enough in {\it Common Lisp: the Language\/} to be useful as classes.
Until the specification of these types is clarified, it would be
counterproductive to have corresponding classes for the types.
\item{\bull} Some types cannot be used for discrimination, such as {\bf
nil} and {\bf values}. No object can be an instance of these types
so there is no advantage to having classes for them.
\endlist
The \CLOS\ specification intentionally leaves room for adding more
standard type classes when these issues are resolved. For example,
when and if the Common Lisp Cleanup Committee provides a relative
precedence order on the types that currently lack them, these types
could have corresponding classes. Similarly, classes could be added
for the types whose specifications are currently too vague, whenever
the types are more rigorously defined.
Question: What were the guidelines for choosing which types would
have a class, and which would not?
The general guidelines were given above. The reasons for excluding
each individual type are given here:
{\it Boolean combinations and negation:\/}
{\bf and}
{\bf atom} - Negation {\bf (not cons}}.
{\bf or}
{\bf not}
{\it Subranges:\/}
{\bf bignum}
{\bf bit}
{\bf fixnum}
{\bf keyword}
{\bf member} - Subrange, if more than one argument is given.
{\bf mod} - Subrange of {\bf integer}.
{\bf satisfies} - Unclear subtype relations.
{\bf simple-array}
{\bf simple-bit-vector}
{\bf simple-string}
{\bf simple-vector}
{\bf standard-char}
{\bf string-char}
{\it The specification of these types is too vague:\/}
{\bf common}
{\bf stream}
{\bf function}
{\bf compiled-function}:
{\it No constraints on the precedence relations to other types:\/}
{\bf package}
{\bf readtable}
{\bf random-state}
{\bf hash-table}
{\bf pathname}
{\it No object can be an instance of this type:\/}
{\bf nil}
{\bf values}
{\it The meaning and existence of these types is
implementation-dependent:\/}
{\bf short-float}
{\bf long-float}
{\bf single-float}
{\bf double-float}
\endSection%{Design Theories of the Integration of Types and Classes}
∂10-Jun-87 1412 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from [192.10.41.223] by SAIL.STANFORD.EDU with TCP; 10 Jun 87 14:12:08 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136747; Wed 10-Jun-87 16:45:41 EDT
Date: Wed, 10 Jun 87 16:44 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706101631.AA15389@hplabsc>
Message-ID: <870610164436.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 10 Jun 87 09:31:14 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>Are you looking at an old version of the document perhaps?
I have the version which was distributed at the March ANSI meeting,
along with the corrections distributed at the same meeting.
That's the same version that I have, so we're all right on that score.
∂10-Jun-87 1627 Bobrow.pa@Xerox.COM Re: SETF- method names
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Jun 87 16:27:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 JUN 87 16:04:43 PDT
Date: 10 Jun 87 16:04 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: SETF- method names
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 9 Jun 87 21:16 EDT
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610-160443-1086@Xerox>
Kempf says: However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
There are two issues here.
1) SETF forms do not guarantee to call a function, and hence there is no
level of indirection one can count on to smash to build a tracing
facility.
2) With generic functions, there is such a level of indirection without
using a name, namely the generic function object. If TRACE were a
generic function that had an implementation dependent method on
GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
∂10-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation Discussion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 21:31:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169962; Wed 10-Jun-87 23:34:53 EDT
Date: Wed, 10 Jun 87 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object Creation Discussion
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870610233442.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
In case you're wondering why you haven't heard from me recently: I'm carrying around
a 70-page sheaf of printout of the recent mail on the subject, which is gradually
getting notes written on it, but I haven't reached any conclusions worth repeating yet.
∂10-Jun-87 2338 RPG
To: common-lisp-object-system@SAIL.STANFORD.EDU
Ad Hoc Solutions
Patrick has provided a good analysis of the problems with initialization.
Let me add a little more to it and then let's think about how to proceed.
Initialization is an exemplar of a category of programs, some of which
will be things that users will want to write for themselves. For example,
suppose someone wants to write a DISPLAY-INSTANCE function that will take
a number of arguments; some of those arguments will be used to
supply information for the positioning of the displayed instance, others will
alter defaults that are normally supplied by the classes in the
class precedence list, where these defaults determine how the display will
look (icons, text, texture, background colors, feature colors, sound,
animation, etc). The end-user will want to customize the display by
defining methods on generic functions that get invoked by DISPLAY-INSTANCE.
In this example, we have the problem of determining the defaults as
contributed from the classes in the class precedence list, the problem
of checking the legality of the arguments, and the problem of distributing
the arguments to the right methods.
These are the same problems as in initialization, and the programmer will
need to define his own methodology for solving them if we use an ad hoc
approach for initialization. Assuming a declarative solution, I can even
imagine a programmer using the initialization mechanism to accomplish his
needs in the DISPLAY-INSTANCE problem.
My question is: Is this category of programs large enough that we need to
work Patrick's third dimension into CLOS? Or should we admit the weakness in
CLOS, because the category is too small or is not important? I don't know the
answer to this, and all I wanted to do was explore whether or not there was
a simple way to add the functionality to CLOS so that the decision is a
no-brainer.
-rpg-
∂11-Jun-87 0746 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 07:46:20 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 07:46:18 pdt
Received: by hplabsc ; Thu, 11 Jun 87 07:45:01 pdt
Date: Thu, 11 Jun 87 07:45:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111445.AA28326@hplabsc>
To: Bobrow.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: SETF- method names
>2) With generic functions, there is such a level of indirection without
>using a name, namely the generic function object. If TRACE were a
>generic function that had an implementation dependent method on
>GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
>
A this would solve the problem nicely, for those cases where the
funcallable object is well defined (fundefs, generic functions,
symbols w. function cell bound, methods, etc.).
The problem remains with SETF forms which take generalized variable
references, like SVREF, since there is currently no way to obtain
the funcallable object corresponding to the SETF "method" (to use
CLtL terminology).
jak
∂11-Jun-87 0819 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 08:19:31 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 08:17:56 pdt
Received: by hplabsc ; Thu, 11 Jun 87 08:16:39 pdt
Date: Thu, 11 Jun 87 08:16:39 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111516.AA28670@hplabsc>
To: Bobrow.pa@Xerox.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: Order of Initialization
Cc: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
>I think one should not depend on the order.
I agree, however, there may be cases where the order does matter.
>Consider the ambiguity
>resulting from two class definitions:
>
>(defclass c1 ()
> ((x :initform (initx1))
> (y :initform (inity))))
>
>(declass c2 (c1)
> ((x :initform (initx2)))
>
>These can be in a file in either order. Which order for eveluation of
>(initx2) and (inity) do you think is correct. I can think of arguments
>for both. Further, consider
>
>(defclass c3 (c1)
> ((z :initform (initz))
> (y :initform (inity2))
> (x :initform (initx3))))
>
In this particular example, the class precedence list for C1
would be:
(C1 STANDARD-OBJECT T)
the initializer for the X slot would be INITX2, and the initializer for
the Y slot would be INITY.
For C2, the class precedence list would be:
(C2 C1 STANDARD-OBJECT T)
and, according to the rules on pg. 1-8:1-9 of 87-002 (and
provided it is decided to stick with them), the initializer
for X would be INITX2 and that for Y would be INITY. If
one uses the class precedence list to impose a global ordering
on initialization, and the lexical order within the class
to impose a local ordering, one could argue that the initialization
order INITX2, INITY would make sense.
>So my choice is 3, the user should not depend on the order.
The kind of example I'm thinking about where the order of
initialization can matter is where some global information is
propagated from one initform to the other via a special, or
initialization of one slot requires previous slots to be initialized.
Like:
(defvar *screen-file-descriptor*)
(defclass window ()
(
(file-info (open-screen-file))
...
)
)
and initialization of the rest of the slots requires the special to
be bound.
I think that if the INITIALIZE-INSTANCE (or whatever is
ultimately agreed to be the name) user customizable method could be
designated the right place to put special initialization needs,
like the requirement for initialization to proceed in a particular
order, then the need for specifying the order within the class
itself goes away. However, it is important that the spec specifically
state that the user cannot depend on the order of initialization
for :INITFORMs, otherwise, someone is bound to do so.
jak
∂11-Jun-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Jun 87 11:03:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 170333; Thu 11-Jun-87 14:02:24 EDT
Date: Thu, 11 Jun 87 14:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: SETF- method names
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706111445.AA28326@hplabsc>
Message-ID: <870611140213.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 11 Jun 87 07:45:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>2) With generic functions, there is such a level of indirection without
>using a name, namely the generic function object. If TRACE were a
>generic function that had an implementation dependent method on
>GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
>
Actually this opens its own can of worms. I can't figure out from CLtL
whether TRACE is intended to be an operation on function names, or on
functions. Perhaps it is intentionally left to the discretion of the
particular programming environment. All I know is that in Maclisp and
Zetalisp it was defined to be an operation on function names; but making
it operate on generic-function and method objects would make it an
operation on functions. Here's an example to show what I mean by the
distinction:
(defun foo (x) (print x))
(let ((f (function foo)))
(trace foo)
(funcall f 105))
If TRACE is an operation on function names, this just prints 105. If it's
an operation on functions, it generates tracing output as well.
A this would solve the problem nicely, for those cases where the
funcallable object is well defined (fundefs, generic functions,
symbols w. function cell bound, methods, etc.).
The problem remains with SETF forms which take generalized variable
references, like SVREF, since there is currently no way to obtain
the funcallable object corresponding to the SETF "method" (to use
CLtL terminology).
You actually mean the funcallable object called by the form that is
returned by the SETF "method"; those type of SETF-"methods" are macros,
unlike CLOS setf-methods, which are functions.
Yes, this is a problem and I don't know of any good answers to it; after
all, the SETF form might well expand into a call to a different function
depending on seemingly minor variations in details of the arguments.
Not a problem for CLOS, just a problem for CL. Your technique of
macroexpanding a sample form and assuming that the function that appears
there is the one that is going to be called is probably as good as any.
∂11-Jun-87 1243 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 12:42:47 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 12:41:51 pdt
Received: by hplabsc ; Thu, 11 Jun 87 12:40:41 pdt
Date: Thu, 11 Jun 87 12:40:41 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111940.AA02450@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@sail.stanford.edu
Subject: Re: SETF- method names
> Date: Thu, 11 Jun 87 07:45:01 pdt
> From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>
> >2) With generic functions, there is such a level of indirection without
> >using a name, namely the generic function object. If TRACE were a
> >generic function that had an implementation dependent method on
> >GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
> >
>
>Actually this opens its own can of worms. I can't figure out from CLtL
>whether TRACE is intended to be an operation on function names, or on
>functions. Perhaps it is intentionally left to the discretion of the
>particular programming environment. All I know is that in Maclisp and
>Zetalisp it was defined to be an operation on function names; but making
>it operate on generic-function and method objects would make it an
>operation on functions. Here's an example to show what I mean by the
>distinction:
>
>(defun foo (x) (print x))
>(let ((f (function foo)))
> (trace foo)
> (funcall f 105))
>
>If TRACE is an operation on function names, this just prints 105. If it's
>an operation on functions, it generates tracing output as well.
>
True, it could complicate implementations. The typical way of dealing
with tracing via names is to wrap the fundef with a wrapper function,
and hang the wrapper off the symbol's function cell. This doesn't demand
anything special of the fundef or symbol, since symbols are typically
writable. If TRACE becomes an operation on fundefs, it's got to modify
the fundef object, perhaps (extrapolating from the implementation
I'm aware of) putting a jump to the trace function as the first instruction
in the fundef. This may get difficult, if fundefs are in restricted
parts of memory, like nonwritable, which often is used for sharing
executable code between processes in different address spaces (again,
in the implementation I know best).
jak
∂12-Jun-87 1002 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Metaclass Protocol
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Jun 87 10:02:05 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad01370; 12 Jun 87 12:54 EDT
Received: from ti-csl by RELAY.CS.NET id ag22147; 12 Jun 87 12:49 EDT
Received: by tilde id AA18373; Fri, 12 Jun 87 11:11:18 CDT
Message-Id: <2759501598-3981583@Jenner>
Date: Fri, 12 Jun 87 11:13:18 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Metaclass Protocol
This message is a first-cut attempt at a design rationale for the
metaclass protocol. The metaclass protocol being quite large, it will
be easier if we discuss and agree on the design rationale first.
We want to standardize the metaclass protocol to meet these objectives:
- Allow for portable compatible extensions to the CLOS model.
1)Some might change the instances representation/behavior while
retaining a compatible top-level interface; Persistent objects systems
and Distributed objects systems are some examples.
2)Some might extend the model by changing the classes behavior like
Delegation instead of Inheritance or they can implement another object
system for backward compatibility reasons (like Flavors, Common
Objects...). It would be desirable to allow a certain degree of
coexistence between classes belonging to different metaclasses.
- Allow for generic high level tools(Inspectors, generators, analyzers).
As a number of extensions will become available, there will be a need
for a single set of tools able to deal equally well with those
extensions.
Requirements:
The metaclass protocol should allow the implementation to pick the best
optimization strategy (in terms of code generation and instance
representation).
The metaclass protocol should allow for any programming development
styles. The idea is that an implementation should be able to support
both smooth incremental development and efficient wholesale file
compilation.
The metaclass protocol should support first class objects and anonymous
generic functions.
- Class behavior and instance behavior are othorgonal in CLOS. The
metaclass protocol must preserve this orthoganality. The metaclass
protocol should be as modular as possible. I would want to be able to
write a Persistent-mixin metaclass and then mix it with STANDARD-CLASS
to get a persistent standard-class or with FLAVORS to get a persistent
flavors metaclass, instead of having to implement a full-blown metaclass
for every case.
I think those objectives and requirements open up some specific issues:
- The side effects on CLOS objects (Classes, generic-functions, methods)
that spead across object links should be exposed.
Compute-class-precedence-list is a good example.
- It should be possible to access some exposed slots of a CLOS object
without side-effect. An inspector may need to access the
Class-precedence-list slot of a class without triggering
compute-class-precedence-list on the class. I think that means we need
to have a way to indicate when a slot contains valid data.
- We probably need to care about the compile environment. We don't have
to specify what it is but where, in our protocol it should be looked up
or side effected. At least we must make sure that we don't go against
the following statements:
1)Compile-file does not side effect the running environment.
2)It is possible to implement a cross loader (Something that loads files
in order to make some class definitions, etc that will affect
the compilation but not the running environment).
The list of requirement and issues is far from being complete, but it
probably covers enough to get the discussion started.
Patrick.
∂12-Jun-87 1204 Bobrow.pa@Xerox.COM Re: Order of Initialization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Jun 87 12:04:07 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 12 JUN 87 11:38:02 PDT
Date: 12 Jun 87 11:37 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Order of Initialization
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Thu,
11 Jun 87 08:16:39 pdt
To: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Message-ID: <870612-113802-1764@Xerox>
I think that if the INITIALIZE-INSTANCE (or whatever is
ultimately agreed to be the name) user customizable method could be
designated the right place to put special initialization needs,
like the requirement for initialization to proceed in a particular
order, then the need for specifying the order within the class
itself goes away. However, it is important that the spec
specifically state that the user cannot depend on the order of
initialization for :INITFORMs, otherwise, someone is bound to do so.
RIGHT (Meaning I agree)
∂15-Jun-87 1118 Gregor.pa@Xerox.COM new new initialization protocol blues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jun 87 11:17:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JUN 87 11:06:40 PDT
Date: 15 Jun 87 11:06 PDT
From: Gregor.pa@Xerox.COM
Subject: new new initialization protocol blues
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM
Message-ID: <870615-110640-1411@Xerox>
Here is another example of a fully procedural initialization protocol.
This message also includes an example of using that protocol to solve
the x-y-rho-theta problem.
In this protocol, make-instance, compute-initargs,
class-default-initargs and class-legal-initargs are documented generic
functions.
The method for make-instance on standard-class is documented to call
compute-initargs and allocate-instance. The method for
allocate-instance on standard-class is documented to allocate storage
and evluate and store all the initforms. The method for
compute-initargs on object is documented to call class-default-initargs
and class-legal-initargs and do the kind of defaulting we have all come
to expect.
Many users will just want to define methods on class-default-initargs
and class-legal-initargs. Users trying to deal with problems like the
x-y-rho-theta problem will usually have to define methods on
compute-initargs as well.
(defmethod make-instance ((class symbol) &rest supplied-initargs)
(apply #'make-instance (class-named symbol) supplied-initargs))
(defmethod make-instance ((class standard-class) &rest
supplied-initargs)
(let* ((proto (class-prototype class))
(total-initargs (compute-initargs proto supplied-initargs))
(instance (apply #'allocate-instance class total-initargs)))
(apply #'initialize-instance instance total-initargs)
instance))
(defmethod compute-initargs ((object object) supplied-initargs)
(let* ((default (class-default-initargs object))
(legal (class-legal-initargs object))
(total supplied-initargs)
(magic-value (list nil)))
(do ((prop default (cddr prop))
(val (cdr default) (cddr val)))
((null prop))
(when (eq (getf total prop magic-value) magic-value)
(push (eval val) total)
(push prop total)))
(do ((prop total (cddr prop)))
((null prop))
(unless (member prop legal)
(error "~S is not a legal initarg for the class ~S"
prop
(class-of object))))
total))
(defgeneric-options class-legal-initargs (class)
(:method-comination-type append))
(defmethod class-legal-initargs ((class object)) '(:allow-other-keys))
(defgeneric-options class-default-initargs (class)
(:method-combination-type append))
(defmethod class-default-initargs ((class object)) ())
;;;
;;; Here is an example of all this in use to solve the notorious
;;; x-y-rho-theta problem.
;;; We define a class named position, which can be mixed into
;;; a class that implements either x-y-position primitives or
;;; rho-theta-position primitives. This class takes care of providing
;;; the other set of primitives, and more importantly takes care of
;;; handling the :x :y :rho :theta defaulting properly.
;;;
(defclass position () ())
(defmethod class-legal-initargs ((pos position))
'(:rho :theta :x :y))
(defmethod class-default-initargs ((pos position))
'((:x 0) (:y 0) (:rho 0) (:theta 0)))
(defmethod compute-initargs ((pos position) supplied)
(let ((x-p (memq ':x supplied))
(y-p (memq ':y supplied))
(r-p (memq ':rho supplied))
(t-p (memq ':theta supplied))
(defaults (class-default-initargs class)))
(when (and (or x-p y-p) (or r-p t-p))
(error "make up your mind loser"))
(cond ((and x-p y-p))
((and r-p t-p))
(x-p
(setf (getf supplied :y)
(eval-default-initarg (getf defaults :y))))
(y-p
(setf (getf supplied :x)
(eval-default-initarg (getf defaults :x))))
(r-p
(setf (getf supplied :theta)
(eval-default-initarg (getf defaults :theta))))
(t-p
(setf (getf supplied :rho)
(eval-default-initarg (getf defaults :rho)))))
(call-next-method pos supplied)))
(defmethod x-position ((p position))
(convert-rho-theta-to-x (rho-position p)
(theta-position p)))
(defmethod y-position ((p position))
(convert-rho-theta-to-y (rho-position p)
(theta-position p)))
(defmethod rho-position ((p position))
(convert-x-y-to-rho (x-position p)
(y-position p)))
(defmethod theta-position ((p position))
(convert-x-y-to-theta (x-position p)
(y-position p)))
(defclass x-y-position (position) (x y))
(defmethod initialize-instance :after
((pos x-y-position) &key x y &allow-other-keys)
(setf (slot-value pos 'x) x
(slot-value pos 'y) y))
(defclass rho-theta-position (position) (rho theta))
(defmethod initialize-instance :after
((pos rho-theta-position) &key rho theta &allow-other-keys)
(setf (slot-value pos 'rho) rho
(slot-value pos 'theta) theta))
∂15-Jun-87 1920 Bobrow.pa@Xerox.COM Re: new new initialization protocol blues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jun 87 19:20:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JUN 87 15:06:21 PDT
Date: 15 Jun 87 15:06 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: new new initialization protocol blues
In-reply-to: Gregor.pa's message of 15 Jun 87 11:06 PDT
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu, Bobrow.pa@Xerox.COM
Message-ID: <870615-150621-108@Xerox>
1) It is useful to be able to allocate storage for an instance without
having to evaluate all the initforms, for example, to build a
class-prototype without risking an error. Either this must be a
function that is called by allocate-instance, or it can be the job of
allocate instance. But in Gregor's message (and my earlier message) we
stated that
The method for allocate-instance on standard-class is
documented to allocate storage and evaluate and store all the
initforms.
A useful alternative may be to make the method for allocate-instance
only allocate storage for the instance. Then the primary method on
object for initialize-instance would be documented to evaluate and store
all the initforms.
2) Gregor's method not only exposes the proposed implementation of
initargs as methods, but suggests that the user must program using this
verbose style. Here is a useful macro, shown only in an example, that
would usually be used by users to specify how to handle inputs to
specify slot-values. The name of the macro can obviously be improved.
User-code:
(define-initialize-instance-after-method x-y-position (pos &key
start-the-engine)
((x :x number "a number") ;; initialize x a slot, checking its
type as a number
(y :second) ;; initialize y as a slot, using
keyword :second
z) ;; initialize z as a slot, using z as
the keyword
(when start-the-engine (fire-up pos))) ;; other user init code
----
Translation:
(defmethod initialize-instance :after
((pos x-y-position) &key start-the-engine
((:x #:g1) nil #:g2)
((:y #:g3) nil #:g4)
((z #:g5) nil #:g6)
&allow-other-keys)
(when #:g2
(check-type #:g1 number "a number")
(setf (slot-value pos 'x) #:g1))
(when #:g4
(setf (slot-value pos 'y) #:g3))
(when #:g6
(check-type #:g5 z-type) ;; this here if :type specified
in the class
(setf (slot-value pos 'z) #:g5))
;; Now comes the user-supplied body.
(when start-the-engine (fire-up pos)))
∂23-Jun-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jun 87 21:13:04 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 180419; Wed 24-Jun-87 00:12:34 EDT
Date: Wed, 24 Jun 87 00:12 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870624001226.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I've been studying the huge piles of mail on this subject. I'm not sure
that all of the ideas that were intended to be conveyed got through to
me, since there was so much mail and so many contradictions and minor
errors. Hence I apologize if what follows misses the point.
I couldn't find anything that directly addressed the issues I raised in
my message of 29 May; the one dividing things up into eight parts, of
which only three are actually needed if we want to keep things simple.
Did it get lost in the network?
My hardcopy of Dick's message of 31 May has "agreed" written all over
it. The conclusion I drew was that we aren't doing automatic
programming here and the generic-function-dispatch mechanism is pretty
limited in what programming tasks it can do automatically for us.
Still, it would be nice if we could come up with a general paradigm for the
procedural description of inheritance and use it uniformly for classes,
methods, slots, and initializations, and also make it available to users
with their own things-that-inherit; I don't have any specific
suggestions on this yet. One thing that I think we have learned is that
it seems to be a mistake to try to abstract away the caching that
happens in every real implementation of inheritance; we need to separate
the generic functions that gather and combine information from the
superclasses, from the generic functions that are called when an object
is created; the cache that sits between them needs to be made explicit.
I do have some thoughts to offer on the various schemes that have been
discussed for object creation at the meta-object level. It seems that
there are three rather different things that this could be for:
(1) The language used by ordinary, rank-and-file programmers to write
their programs.
(2) A procedural explanation of the semantics, so that there is no
magic and everything is explained in terms of something else. This
seems to be where Patrick's suggested generic, high-level tools fit in.
(3) A way to modify very basic aspects of the system's behavior,
for instance changing the way initargs inherit.
Taking these in order:
(1) I feel that a successful standard will provide simple ways to do
simple things. A good argument that controlling object creation only at
the meta-object level is too difficult is contained in Gregor's message
of 15 June. In the x-y-rho-theta example, the compute-initargs method
for position looks impressive, but if you study it carefully you will
realize that it is actually a complicated no-op! Regardless of whether
this method or the default method is called, the result will be the
same: a list containing the supplied initargs plus all of the
unsupplied ones with their default values from class-default-initargs.
I suspect that what happened here is that Gregor got so bogged down in
the complexity of describing the x/y/rho/theta class in these very
low-level procedural terms, that he forgot what the original point was.
Gregor is a smart guy, so I think what this shows is that an
object-oriented system that works this way is too difficult for anyone
to use without making mistakes.
Actually, this is probably a non-issue. Correct me if I am wrong, but
I think we have already agreed that we want a simple, high-level way to
do simple object-creation, with the procedural level behind the scenes
where it belongs.
(2) I think having a procedural explanation of the semantics is a good
idea. If I earlier gave the impression that I was opposed to that, it
was a misimpression. I do have some reservations, which I think fall
into two categories:
(a) This level of the standard involves a lot more detail than the
simple programmer interface, and there is correspondingly more
possibility for errors. Two examples that I noticed were failure to
carry along a lexical environment with forms, so that they can be
evaluated in the lexical environment in which they were written; and
confusion between method selection by the class of the instance versus
by the class of the class. These are small errors and fairly easy to
fix. For example, the first could be fixed by using functions instead
of forms and the second could be fixed by being consistent. The point
is simply that there are more things to go wrong and it will take longer
to get them right, because we are standardizing an implementation (at
some level of abstraction) rather than standardizing only a description
of how any implementation must behave.
(b) There is the danger of ripping too many holes in the veil of
abstraction between the user and the implementation, eliminating the
freedom to choose an implementation optimized for particular
circumstances. We have often made this mistake in the Lisp Machine
world in the past, and paid for it later. One example of this problem
is that I haven't been able to figure out whether some of the proposals
that have been discussed require the methods for class-default-initargs
to be called every time make-instance is called, thus ruling out
precomputation and caching of this information. Similarly I wasn't able
to figure out whether initializing many of the slots by copying a
template containing the values of constant initforms would be a valid
implementation, or whether the initforms actually have to be evaluated
at the time we say they are evaluated. A more serious problem is that
if the two operations, collection of the inherited default value forms
and evaluation of these forms, are combined into one generic function,
such as compute-initargs, it becomes impossible to collect these forms
without evaluating them and compile them into a function. This is
really the same point I made earlier, that trying to hide the existence
of caches isn't working. A third problem, which I mention because it's
of a completely different nature, is that if the standard mandates that
each little aspect of a class must be expressed as a method, and we
actually have to create method objects, compiled-function objects, and
generic-function dispatch table entries for each of those methods, it's
going to tie up a large amount of space. In a large system like Genera,
a rough, no doubt inaccurate estimate I made came out to 3/4 megabyte.
The point of these reservations is that if we're going to include this
level of detail in the standard, we have to be very careful what we say
and be sure we know what it implies.
(3) I'm not very happy about the idea of the user being able to redefine
very basic aspects of the behavior of the system, such as the way the
supplied initargs are combined with the default initargs. It seems like
this would weaken the idea of a standard, because there would be no
contract that the system could safely be assumed to obey. Actually what
bothers me here is not the idea that it is possible to redefine these
things, because I'm an open-system kind of guy and if people want to yank
the foundations out from under themselves that's okay with me. What really
bothers me is the idea that redefining this stuff will be part of ordinary
day to day programming, rather than just something that you do when you're
experimenting with new kinds of object systems; changing the rules should
be intentional, not accidental.
Where do we go from here? I think we should go back to figuring out
what the language used daily by rank-and-file programmers is. Once we
think we agree on that, we should verify that it makes sense by agreeing
on the procedural description of it; there will be some iteration of
these two steps (there has already been some). The biggest issue seems
to be what suite of features we want in that language, for example, is
the extra complexity of allowing initargs to be defaulted worthwhile?
∂24-Jun-87 1045 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jun 87 10:45:11 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 180885; Wed 24-Jun-87 12:59:08 EDT
Date: Wed, 24 Jun 87 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object Creation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870624125852.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here's how I would do the x/y/rho/theta example:
;;; Abstract class that can be specialized to use either
;;; polar or cartesian representation
(defclass position () ())
(defmethod initialize-instance :before
((self position) &key x y rho theta)
(when (or x y)
(set-cartesian-position self (or x 0) (or y 0)))
(when (or rho theta)
(set-polar-position self (or rho 0) (or theta 0))))
;;; Default methods. One pair or the other must be shadowed.
(defmethod cartesian-position ((self position))
(multiple-value-call #'polar-to-cartesian (polar-position self)))
(defmethod set-cartesian-position ((self position) x y)
(multiple-value-call #'set-polar-position
self (cartesian-to-polar x y)))
(defmethod polar-position ((self position))
(multiple-value-call #'cartesian-to-polar (cartesian-position self)))
(defmethod set-polar-position ((self position) rho theta)
(multiple-value-call #'set-cartesian-position
self (polar-to-cartesian rho theta)))
;;; Internal subroutines for coordinate transformation
(defun polar-to-cartesian (rho theta)
(values (* rho (cos theta))
(* rho (sin theta))))
(defun cartesian-to-polar (x y)
(if (and (zerop x) (zerop y))
(values 0 0)
(values (sqrt (+ (* x x) (* y y)))
(atan y x))))
;;; Useful macro
(defmacro with-direct-slots ((instance) &body body)
`(with-slots ((,instance :use-accessors nil))
,@body))
;;; Instantiable class that uses cartesian representation
(defclass cartesian-position (position) (x y))
(defmethod cartesian-position ((self cartesian-position))
(with-direct-slots (self)
(values x y)))
(defmethod set-cartesian-position ((self cartesian-position)
new-x new-y)
(with-direct-slots (self)
(setq x new-x y new-y)))
;;; Instantiable class that uses polar representation
(defclass polar-position (position) (rho theta))
(defmethod polar-position ((self polar-position))
(with-direct-slots (self)
(values rho theta)))
(defmethod set-polar-position ((self polar-position)
new-rho new-theta)
(with-direct-slots (self)
(setq rho new-rho theta new-theta)))
∂24-Jun-87 1155 RPG Request to Moon for Thursday's Discussion
To: common-lisp-object-system@SAIL.STANFORD.EDU
Dave, could you possibly gather some information about the
current uses of initialization in Genera? It would be useful to
know what the most complex requirements are, what the typical
requirements are, etc, in a real system. For example, how often would
the CLOS :initform protocol serve?
-rpg-
∂25-Jun-87 0901 RPG Random Thoughts Concerning Initialization
To: common-lisp-object-system@SAIL.STANFORD.EDU
Reading over Gregor's latest proposal I am struck by the choices
we have:
1. In Moon's proposal, we introduce a new programming language within
the DEFCLASS syntax. This language solves the initialization problem
efficiently with minimal syntax. Other problems reducable to initialization
might also be so reduced by users, leading to confusing programming
methodologies.
2. In Gabriel's proposal, we introduce some additional lambda-list syntax
and semantics to effect the distribution of arguments to methods. This
also requires complex initialization protocol to be written in a verbose
manner, and it complicates lambda-lists in an unpleasant manner.
3. In Gregor's proposal, we solve the initialization problem by reducing
it to a problem of manipulating argument lists. The code (sans macros) is
verbose and complicated. In addition, we end up treating passed arguments
as lists, which I find to be an unpleasant exposure of representation.
If we approach the initialization question along the lines Gregor
suggests, and if we look at the nature of generic functions (dispatching
to code based on examination of passed arguments), it seems there is some
tendency towards introducing into the language a means of operating on
passed arguments. One reason we had trouble with generic functions that
discriminated on more than the required arguments is that we had a hard
time manipulating the passed arguments.
If we choose a solution to initialization that involves manipulating
passed arguments, we possibly ought to provide an abstraction for passed
arguments - a set of passed arguments along with a set of operators that
take them apart, put them together, and invoke functions on them? I
believe Seus [Talcott] went some distance in this direction.
∂02-Jul-87 0911 kempf%hplabsc@hplabs.HP.COM ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Jul 87 09:11:09 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 2 Jul 87 09:10:20 pdt
Received: by hplabsc ; Thu, 2 Jul 87 08:35:59 pdt
Date: Thu, 2 Jul 87 08:35:59 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8707021535.AA22501@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: ECOOP Reaction to CLOS
My impression from talking to people at ECOOP was that most people
were fairly positive about Dick's talk.
He did get some flak about the inheritance algorithm, but I think this
was due to the presentation. If you tell someone that something is
too complicated to understand, the likely response is that you should
make the design simpler so they can understand it. In my opinion, it
is simply unacceptable to go around saying this. The algorithm isn't
any more complicated than the one used for LR parser generation
(to which Aho, Sethi, and Ullman devote 37 pages in the new Dragon
book) or normalization of a relational database schema (to which
Date devotes 23 pages).
The fact that the algorithm is the right one is bostered by a paper
by Ducournau and Habib at ECOOP, which examined a class of graph
linerization algorithms having desirable qualitative properties,
of which the CLOS algorithm is a member.
Therefore, I hope someone can stand up at OOPSLA and do a better
job of explaining it. It may take some time, and will probably
require some more examples, particularly of how things can go
wrong, but I think it will, in the end, gain more support for
CLOS and increase programmer understanding. People should feel
good about using it, not just because its the standard, but also
because it does what they want and they understand that.
I hope someone will post the results of the Boston meeting, particularly
any decisions on initialization.
Jim Kempf kempf@hplabs.hp.com
∂03-Jul-87 0843 Moon@STONY-BROOK.SCRC.Symbolics.COM ECOOP Reaction to CLOS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jul 87 08:43:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 187240; Thu 2-Jul-87 16:58:59 EDT
Date: Thu, 2 Jul 87 16:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: ECOOP Reaction to CLOS
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8707021535.AA22501@hplabsc>
Message-ID: <870702165857.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 2 Jul 87 08:35:59 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
I hope someone will post the results of the Boston meeting, particularly
any decisions on initialization.
Definitely. Because of the long weekend, and because Gregor will be off
work Monday and Tuesday, you can expect to see this around the second half
of next week. I wouldn't say we made any hard and fast decisions, but we
certainly made a lot of progress and we should be able to finish that up
and make actual decisions through the mail. We talked about having another
meeting and the scheduling for that will have to be discussed through the
mail.
∂06-Jul-87 1130 RPG ECOOP Reaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
As Kempf points out, there was some negative reaction to CLOS at my
presentation, but most of it was directed at the lack of encapsulation and
protection, multiple inheritance, and the use of CLOS as a knowledge
representation system. I might point out that most of the people who
raised objections during the presentation came up to me afterwards to get
a hold of the spec, the code, etc.
I want to make clear what it is I said about the CPL computation: I stated
that the effect of the CPL algorithm was difficult to understand, not that
the algorithm is difficult to understand. The difference between the two
is that an algorithm can be easy to grasp while a characterization of it
suitable for a programmer to understand is not available. In contrast,
the algorithm for computing the strongly connected components of a graph
is easy to understand as an algorithm, and it is easy to understand what
it does because the definition of a strongly connected component is easy
to understand. The CPL is understood to be a total ordering on a class
and its superclasses, but the only characteriztion of it that I know of is
that the CPL is the total ordering computed by the algorithm. That
algorithm is understandable at the operational level, but there is no easy
characterization of it.
What would constitute an understandable characterization of the CPL?
Here are some examples of approaches:
1. We could have a set of constraints on the classes such that the CPL
is the unique total ordering satisfying those constraints.
2. We could have a set of inheritance situations such that when two
graphs of classes were inherited in particular ways, the new CPL was
predictable. For example, suppose we have 2 graphs, G1 and G2, with no common
classes except for the class named T and suppose that C1 and C2 are the
bottom-most classes of G1 and G2, respectively; then if a class C is
a subclass of C1 and C2 in that order, the classes in G1 precede the classes
in G2, and the classes in G1 are in the same order as they are in the CPL
for C1 and similarly for G2; T comes last.
But we do not have such a characterization; Moon's constraints are close
to it, but not good enough. Possibly we can search for the
characterization. Remember that at the Palo Alto meeting in March, smart
people like Scherlis could not understand the effect of the algorithm,
although they (and he) thought the algorithm was simple.
Intellectual honesty compels me to point out things like this when
I address an audience. I suppose it annoys people when I do that,
but maybe we should give some thought to designing a language such that
there are few oppurtunities for ``Gabriel's inevitable critique.''
-rpg-
∂08-Jul-87 0928 RPG First Try at Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
At the Symbolics meeting we decided to introduce some terminology
about erroneous situations for use in the final document. Here is
a first attempt at that terminology - Sit is a situation and Syn is
syntax:
The terminology defined in 1 - 4 refers to situations that might occur,
while the terminology defined in 5 refers to syntax.
A ``situation'' is one of the following:
1. an expression in which the first form is given or specified and
the remaining subexpressions are either given, specified, or
evaluate to objects satisfying certain constraints;
2. a state of affairs within a running CLOS system.
Examples: When the function + is given a non-number as an argument, that
is a situation under definition 1; when a numeric operation causes an
arithmetic overflow, that is a situation under definition 2.
``Syntax'' refers to the nature of the lambda-list of a function,
the nature of the defmacro lambda-list of a macro, and the number and
nature of the subexpressions in a special form.
In the specification of CLOS, the behavior of programs in all situations
is described, and the options available to the implementor are defined; no
implementation is allowed to extend the syntax or semantics of CLOS except
as explicitly defined in the CLOS specification. In particular, no
implementation is allowed to extend the syntax of CLOS in such a way that
ambiguity between the specified syntax of CLOS and those extensions is
possible.
The following are descriptive phrases and their meanings:
1. ``When Sit occurs an error is signaled.''
The meaning of this terminology is:
a. If this situation occurs, an error will be signaled in code
compiled under all compiler safety optimization levels and in
the interpreter.
b. Valid CLOS programs may rely on the fact that an error will be
signaled in code compiled under all compiler safety
optimization levels and in the interpreter.
c. Every CLOS implementation is required to detect such an error
in code compiled under all compiler safety optimization levels
and in the interpreter.
2. ``When Sit occurs an error should be signaled.''
The meaning of this terminology is:
a. If this situation occurs, an error will be signaled at least in
code compiled under one compiler safety optimization level and
in the interpreter.
b. Valid CLOS programs may not rely on the fact that an error will be
signaled.
c. Every CLOS implementation is required to detect such an error
at least in code compiled under one compiler safety
optimization level and in the interpreter.
d. When an error is not signaled, the results are undefined (see
below).
3. ``When Sit occurs the results are undefined.''
The meaning of this terminology is:
a. If this situation occurs, the results are unpredictable. The
results may range from harmless to fatal to the running CLOS
system.
b. No valid CLOS programs should cause this situation to happen.
c. CLOS implementations are allowed to detect this situation and
signal an error, but no CLOS implementation is required to
detect the situation.
d. No implementation is allowed to extend the semantics of CLOS to
this situation; the effects of the situation may be harmless,
but they must remain undefined.
4. ``CLOS may be extended to cover Sit.''
The meaning of this terminology is that an implementation is free to treat
Sit in one of four ways:
a. When Sit occurs, an error is signaled;
b. When Sit occurs, an error is signaled at least in code compiled
under one compiler safety optimization level and in the
interpreter.
c. When Sit occurs, the results are undefined; or
d. When Sit occurs, the results are defined and specified.
In addition, this terminology means that:
e. No portable CLOS program can depend on the effects of this
situation, and all portable CLOS programs are required to treat
the situation as undefined.
5. ``Implementations are free to extend the syntax Syn.''
The meaning of this terminology is:
a. Implementations are allowed to define unambiguous extensions to
that syntax.
The CLOS specification may disallow certain extensions while allowing others.
*****************************************************************************
The following is a discussion of the motivation behind these terms. Of course,
there is no commitment yet to these terms: This is simply the first proposal.
The definition of a situation is designed to cover function invocations,
macro calls, and instances of the use of special forms as well as
conditions that might arise within a running CLOS system. A situation is
not a purely syntactic state of affairs, because the preconditions for an
error usually requires that something about the nature of the arguments
to a function, for example, be known. The wording of these definitions will
need further work.
On syntax, I believe we want the default to be that no extensions are
allowed - that is, any extensions must be explicitly allowed. I
particularly wish to disallow syntactic extensions that extend the number
of arguments to a function or a macro or the number of subexpressions in a
special form.
These terms are a reaction to current CLtL terminology and the various
interpretations of it. The entire gamut of interpretations of CLtL terms
is valid, but there are more interpretations than terms. This proposal is
intended to identify the reasonable interpretations of CLtL terminology
and provide terms for those intepretations, so that, I hope, the terms and
interpretations are one-to-one.
1. ``When Sit occurs an error is signaled.''
This term is borrowed from CLtL. I think we need a more precise definition
that talks about errors being signaled in code compiled under all compiler
optimization levels. Current practice in Common Lisp includes only
signaling errors in code that was compiled under high compiler safety
optimization levels. Because there is a constant desire to elide such
checks in compiled code on stock hadware, we should separate out cases in
which we want errors signaled in code compiled under all compiler
optimization levels from those in which we allow implementations to
provide a high-speed, unsafe operations - my recollection is that CLtL
``is an error'' was intended to accomplish that separation, but that is
not the current prevailing interpretation. Hence the term:
2. ``When Sit occurs an error should be signaled.''
Some people who interpret CLtL maintain that, under a strict reading of
CLtL, CLOS ``signals an error'' corresponds to CLtL ``signals an error''
and CLOS ``an error should be signaled'' corresponds to CLtL ``is an
error.'' This does not correspond to current practice, in which CLtL
``signals an error'' generally corresponds to CLOS ``signals an error''
or ``should signal an error,'' while CLtL ``is an error'' generally
corresponds to CLOS ``is undefined'' or ``is extendable.''
3. ``When Sit occurs the results are undefined.''
The intention of this is to allow implementations to not worry about what
happens in Sit, because CLOS does not permit programs to be written that
fall into Sit, and no implementation is allowed to extend the semantics of
CLOS to provide useful behavior in Sit. Some people have claimed that CLtL
``is an error'' corresponds to CLOS ``is undefined.''
I might expect that we would add wording to this to the effect that an
implementation may include documentation about a situation of this sort
that states that the results are harmless, but no implementation is
allowed to state what actually happens.
4. ``CLOS may be extended to cover Sit.''
This term in intended to cover yet another reading of CLtL ``is an
error,'' namely that an implementation is allowed to extend the language
to cover an otherwise erroneous situation.
5. ``Implementations are free to extend the syntax Syn.''
I believe we wish to control where extensions to CLOS are allowed to occur.
The first four terms are designed to control semantic extensions while the
fifth is designed to control syntactic extensions, which are somewhat
different.
I believe we want to define precise terms such as these and use them
exactly in the CLOS specification so that, rather than the CLOS
specification being a pseudo-user's-guide as CLtL is, it can be a
specification suitable for an implementor.
-rpg-
∂08-Jul-87 0938 RPG Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
One minor point that came up at the Symbolics meeting last Thursday
was category errors and whether we should try to outlaw them somehow.
Here is an example of a category error:
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
(make-instance (class-prototype (class-named 'apple-pie)) ...)
Here someone would be making a category error by defining a method on
MAKE-INSTANCE at the wrong level - the class level. What makes this easy
for a programmer to do this is the availability of CLASS-PROTOTYPE.
However, it is never hard to do because the programmer can write:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
to get his class prototype.
We have two alternatives:
1. Let sea of classes/metaclasses remain a miasma and inform
programmer that he ought not mix things up.
2. Define a notion of class category or classs level and have a
category of generic function for each class category.
-rpg-
∂08-Jul-87 1643 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 8 Jul 87 16:43:20 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa01894; 8 Jul 87 19:38 EDT
Received: from ti-csl by RELAY.CS.NET id aa05802; 8 Jul 87 19:31 EDT
Received: from Jenner by tilde id AA05525; Wed, 8 Jul 87 16:05:23 CDT
Message-Id: <2761765326-16486571@Jenner>
Date: Wed, 8 Jul 87 16:02:06 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Class redefinition and class-changed.
Redefining a class will provoke instances of this class to be changed to the new
class using the change-class protocol. However there is no specified way to
take advantage of the class-changed generic function.
Goals:
- There should be a way to define a method for class-changed on the obsolete
class and the class.
- This method needs to be defined before any the instances is changed,
otherwise it wouldn't get invoked on all the instances of the class.
Proposal:
Before committing the class to redefinition, we specify a way to get the
obsolete class objects and thus, define methods for class-changed. Since a
class redefinition will propagate down, it will be useful to get the closure of
all the redefintions.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION will return an alist whose keys are the
classes implicated in the class-redefinition of CLASS and whose contents are the
obsolete classes.
Syntax:
GET-OBSOLETE-CLASSES-FOR-REDEFINITION CLASS &optional (REDEFINITION-CLOSURE-P t)
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is a generic function.
CLASS is a class object
if REDEFINITION-CLOSURE-P not provided or non nil, all the classes implicated in
the class redefinition of CLASS are returned as keys of the resulting alist. If
REDEFINITION-CLOSURE-P is nil, then the alist returned contains only one entry
for CLASS.
Besides obsolete class creation, get-obsolete-classes-for-redefinition does not
side effect. In other words, it it OK to call it more than once and the returned
obsolete classes are EQ from one call to the other.
Once the methods are defined, the class redefinition can be executed.
Patrick.
∂09-Jul-87 1207 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 12:07:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUL 87 11:54:12 PDT
Date: 9 Jul 87 11:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Wed, 8 Jul 87 16:02:06 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870709-115412-4166@Xerox>
Goals:
- There should be a way to define a method for class-changed
on the obsolete class and the class.
- This method needs to be defined before any the instances is
changed, otherwise it wouldn't get invoked on all the instances of
the class.
Agreed.
The necessary and sufficient condition for this is to be able to get
hold of an obsolete version of a class.
Proposal:
Changing a class updates a database to allow the following generic
functions to work.
GET-OBSOLETE-VERSION class
returns the preceding obsolete version of this class, or NIL if none.
This allows users to define methods at any time on the obsolete class.
Obsolete classes themselves may also have an obsolete-version. Obsolete
classes also respond to
GET-UPDATED-VERSION obsolete-class
with the next class or NIL
This allows following the chain in the opposite direction
Providing this chain allows defining pair-wise updaters from an obsolete
to its updated version, a general updating protocal that will follow the
chain from any old version to the current version, and accelerators
between any old-version and any later version on the chain.
∂09-Jul-87 1326 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:26:09 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:24:30 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:23:58 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:24:38 pdt
Date: Thu, 9 Jul 87 13:24:38 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092024.AA22131@hplabsz.hpl.hp.com>
To: rpg@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
Cc: common-lisp-object-system@sail.stanford.edu
>I want to make clear what it is I said about the CPL computation: I stated
>that the effect of the CPL algorithm was difficult to understand, not that
>the algorithm is difficult to understand. The difference between the two
>is that an algorithm can be easy to grasp while a characterization of it
>suitable for a programmer to understand is not available. In contrast,
>the algorithm for computing the strongly connected components of a graph
>is easy to understand as an algorithm, and it is easy to understand what
>it does because the definition of a strongly connected component is easy
>to understand. The CPL is understood to be a total ordering on a class
>and its superclasses, but the only characteriztion of it that I know of is
>that the CPL is the total ordering computed by the algorithm. That
>algorithm is understandable at the operational level, but there is no easy
>characterization of it.
I think what most programmers want is a two sentence explanation of how
inheritance works in CLOS. The equivalent for Smalltalk is:
Child classes get all the methods and all the slots of
their parents. Any methods defined with the same name
as the parent defined in the child override the parent's
method.
I propose this for CLOS:
The inheritance graph is searched depth first, left to
right, up to joins. Superclasses at joins are placed
in the class precedence list at the last occurance,
rather than the first, since such superclasses are
usually more general than their subclasses, and classes
at the end of the class precedence list should be more
general than those at the beginning. The qualitative
effect is to achieve a linearization of the inheritance
graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph.
Well, that's three sentences, but I think most people won't mind.
A more detailed explantion should go into what can go wrong. The
Ducournau and Habib paper discusses this in a more formal way.
The essense is that if two or more subclasses share two
or more join superclasses, then the algorithm can fail.
In such cases, the two join superclasses are two alternative end
elements for the sublist CPL containing the subclasses, so there
is no unique linearization. Scherlis's comments about programmer
hooks at the Palo Alto meeting might be appropriate here, since
the programmer could choose which join superclass is more
general, but I think the appropriate place to put in these hooks
is the metaobject protocol, and not something like prompting the
programmer.
>Intellectual honesty compels me to point out things like this when
>I address an audience. I suppose it annoys people when I do that,
>but maybe we should give some thought to designing a language such that
>there are few oppurtunities for ``Gabriel's inevitable critique.''
I have no problem with such critiques, however, I think at some point
we need to iterate to a design which we all feel comfortable with,
and which application developers can use. My impression of the
inheritance algorithm is that it refines and solidifies current practice
which is *precisely* what a standard should do. Whether or not it
is the ultimate in linguistic software reuse mechanisms is another
question. I don't think it is, but until I know the answer, have
tested it with a couple of applications, and have discussed it extensively
with other people, I'm sure not going to recommend that it be made a
standard.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1327 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:26:44 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:25:13 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:24:51 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:25:28 pdt
Date: Thu, 9 Jul 87 13:25:28 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092025.AA22144@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Category Errors
>
> 1. Let sea of classes/metaclasses remain a miasma and inform
> programmer that he ought not mix things up.
>
> 2. Define a notion of class category or classs level and have a
> category of generic function for each class category.
This is a difficult one, and relates to Patrick's goal of maintaining metaclass
protocol and class protocol orthogonally. Pros are that it can avoid having
programmers make mistakes like defining MAKE-INSTANCE on a class, as cited
in the base note, cons are that a programmer might actually *want* to have
a particular class be instantiated slightly differently. Given Lisp's
tendency to allow a programmer to do anything, as long as the name for
doing it can be found, I think 1) should be the choice, except the "sea
of classes/metaclasses" ought probably to be broken up into little bays
and gulfs via. the package system. With some method names (like MAKE-INSTANCE)
there is no hope, since they are firmly in the programmer interface.
With the rest of the metaobject protocol, the names should be exported
from a seperate package, so that only programmers who want to do metaclass
programming need be concerned with them. One can reasonably argue that
a programmer using CLOS should be familar enough with the programmer
interface functions to be able to avoid an accidental redefinition of
the methods there, but we should certainly not require CLOS programmers
to be familar with metaclass names unless they intend to do metaclass
programming.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1329 kempf%hplabsz@hplabs.HP.COM Re: First Try at Terminology
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:29:00 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:27:28 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:27:01 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:27:41 pdt
Date: Thu, 9 Jul 87 13:27:41 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092027.AA22154@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: First Try at Terminology
>The definition of a situation is designed to cover function invocations,
>macro calls, and instances of the use of special forms as well as
>conditions that might arise within a running CLOS system. A situation is
>not a purely syntactic state of affairs, because the preconditions for an
>error usually requires that something about the nature of the arguments
>to a function, for example, be known. The wording of these definitions will
>need further work.
Why not go one step further and use preconditions
and postconditions on the functions and macros, ala` Hoare logic?
Example from 87-002 spec (RET is the returned value, ARG the argument):
CLASS-OF
Pre: T
Post: RET is an element of C, the set of defined classes, if ARG is an
instance of a class | error
The postconditions could contain error postconditions of three types:
1) errors at all optimization levels (1 in the original message)
2) errors at the lowest only (2 in the orignal message)
3) errors which implementations are permitted to extend CLOS to
cover.
>I believe we wish to control where extensions to CLOS are allowed to occur.
>The first four terms are designed to control semantic extensions while the
>fifth is designed to control syntactic extensions, which are somewhat
>different.
Yes, this is a laudable goal, but I fear that any attempt to do this
in English may remain open to ambiguous interpretation.
>I believe we want to define precise terms such as these and use them
>exactly in the CLOS specification so that, rather than the CLOS
>specification being a pseudo-user's-guide as CLtL is, it can be a
>specification suitable for an implementor.
100% agreement. Barring any agreement on more rigorous formalism, I
can live with the terminology in the base note. It's a whole lot better
than CLtL.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1333 kempf%hplabsz@hplabs.HP.COM Re: Metaclass Protocol Goals
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:32:33 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:30:54 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:30:20 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:30:59 pdt
Date: Thu, 9 Jul 87 13:30:59 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092030.AA22198@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Metaclass Protocol Goals
Patrick's design rationale looks like a good beginning, and would be a good
addition to the beginning of 87-003, as motivation for the metaclass
protocol. I had a couple of comments and questions:
>Class behavior and instance behavior are othorgonal in CLOS. The
>metaclass protocol must preserve this orthoganality.
I'm not quite sure I understand what you mean by class and instance
behavior being orthogoal. Since class objects are instances of
the metaclass, this statement would seem not to be true for classes
when considered as instances.
>- The side effects on CLOS objects (Classes, generic-functions, methods)
>that spead across object links should be exposed.
>Compute-class-precedence-list is a good example.
I'm not sure I understand what you mean by "be exposed". What I
think you mean by "side effects on CLOS objects that spread across
object links" is protocols which affect objects whose structure acts
as templates for other objects (is that so?). As an example, the
structure of a class object acts as a template for instances. If
you mean that methods affecting the structure of such "template
objects" should be included in the public metaobject protocol, then
I agree.
>- It should be possible to access some exposed slots of a CLOS object
>without side-effect.
I agree with this, but I think it might be difficult to achieve in
practice. With method combination, it should be possible for the designer
of a metaclass to define a daemon method on any method in the protocol
which cause side effects to occur. I can think of a couple solutions to
this off the top of my head. One is to suggest that metaclass programmers
follow a convention of not defining daemon methods which cause side
effects, another is to specifically forbid defining daemon methods on
metaclass methods, possibly through a declaration mechanism (as I
suggested in an earlier note this spring). Probably the former is better,
since daemon methods for doing things like updating browsers when
classes are defined might be useful.
>- We probably need to care about the compile environment. We don't have
>to specify what it is but where, in our protocol it should be looked up
>or side effected. At least we must make sure that we don't go against
>the following statements:
>1)Compile-file does not side effect the running environment.
>2)It is possible to implement a cross loader (Something that loads files
>in order to make some class definitions, etc that will affect
>the compilation but not the running environment).
Given the design of the Common Lisp, this might be very
difficult to achieve. Using the PCLOS implementation from Gregor,
I tried a quick and dirty implementation of a seperate compile time
namespace for CommonObjects on CLOS and ran into some serious problems.
Basically, for languages such as CommonObjects which compute alot of
their inheritance information at compile time, the only alternative
to side effecting the compile time environment is to somehow maintain
the information and update global structures only when its safe. This
approach is used in our native code CommonObjects implementation, and
it is expensive. The CommonObjects on CLOS compiles about twice as
fast because it just side effects the compile time environment. In the
CLOS language, if attention is not paid to side effects, then classes
need to be defined in the compile time environment so that method
definintions being defined in the same file (a logical way to organize
a body of software) can be compiled.
Aside from problems with bootstrapping CLOS itself (which Gregor
seems to pretty well have under control in the portable implementation),
much of the reason for not side effecting the compile time environment
goes away with multiple virtual address spaces. A "spoiled" compile
time environment can just be thrown away. Of course, this doesn't
solve the problem for machines where multiple virtual address spaces
are not an option.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1355 Kahn.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:55:05 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 09 JUL 87 13:49:06 PDT
Date: Thu, 9 Jul 87 13:48:39 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
Subject: Re: Category Errors
In-Reply-To: <8707092025.AA22144@hplabsz.hpl.hp.com>
To: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870709-134906-4431@Xerox>
I think it would be a mistake to build barriers between class and
metaclass protocols. One of the strong appeals of CLOS is that one can
experiment within its framework. We once worked out how Object Lisp's
view that classes and instances are pretty much the same could be
implemented in PCL. A good fraction of the OOP community believes in
these "prototypes" which unify classes and instances. We should be
careful not to prohibit CLOS from evolving in that direction if people
come to believe its a win.
References
kempf%hplabsz@hplabs.HP.COM's message of Thu, 9 Jul 87 13:25:28 PDT --
Re: Category Errors
∂09-Jul-87 1431 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 14:31:26 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 14:28:00 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 14:27:40 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 14:28:20 pdt
Date: Thu, 9 Jul 87 14:28:20 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092128.AA22639@hplabsz.hpl.hp.com>
To: Kahn.pa@Xerox.COM, kempf%hplabsz@hplabs.HP.COM
Subject: Re: Category Errors
Cc: common-lisp-object-system@sail.stanford.edu
>I think it would be a mistake to build barriers between class and
>metaclass protocols. One of the strong appeals of CLOS is that one can
>experiment within its framework. We once worked out how Object Lisp's
>view that classes and instances are pretty much the same could be
>implemented in PCL. A good fraction of the OOP community believes in
>these "prototypes" which unify classes and instances. We should be
>careful not to prohibit CLOS from evolving in that direction if people
>come to believe its a win.
>
I agree with this viewpoint in principle, which is why I wouldn't want
to see any stronger barriers be erected than packageization. That seems
to me to be the minimum to keep people happy who want to maintain some
distance and are already uncomfortable with the metaclass protocol,
and those who believe that no barriers are appropriate. Someone wanting
to implement Object Lisp need only use both the user interface and
metaclass symbols.
∂09-Jul-87 1933 Bobrow.pa@Xerox.COM Re: Metaclass Protocol Goals
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 19:32:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUL 87 19:03:04 PDT
Date: 9 Jul 87 19:03 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Metaclass Protocol Goals
In-reply-to: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>'s message of Thu, 9
Jul 87 13:30:59 pdt
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870709-190304-4903@Xerox>
Patrick>- It should be possible to access some exposed slots of a
CLOS
object >without side-effect.
Jim> I agree with this, but I think it might be difficult to achieve
...
It is not difficult to document for CLOS. If a package adds behavior to
CLOS, then a user of that package should document its behavior. This is
not a matter for program control -- just for social control.
∂10-Jul-87 1026 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 10 Jul 87 10:25:57 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae21575; 10 Jul 87 11:54 EDT
Received: from ti-csl by RELAY.CS.NET id ag17093; 10 Jul 87 11:47 EDT
Received: from Jenner by tilde id AA26237; Fri, 10 Jul 87 10:04:49 CDT
Message-Id: <2761916421-9049515@Jenner>
Date: Fri, 10 Jul 87 10:00:21 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 9 Jul 87 11:51 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
Date: 9 Jul 87 11:51 PDT
From: Danny Bobrow <Bobrow.pa@xerox.com>
Subject: Re: Class redefinition and class-changed.
Goals:
- There should be a way to define a method for class-changed
on the obsolete class and the class.
- This method needs to be defined before any the instances is
changed, otherwise it wouldn't get invoked on all the instances of
the class.
Agreed.
The necessary and sufficient condition for this is to be able to get
hold of an obsolete version of a class.
I don't agree. We said in chapter 1 that the updating of the instances is done
at an implementation-dependent time. It means that unless you prepare your
methods in advance (before the class is actually redefined) you are going to let
some instances be updated without proper class-changed method invokation. The
worst part is you may not find out about it. A necessary condition is to be
able to get hold of an obsolete version of a class before the class is changed.
Proposal:
Changing a class updates a database to allow the following generic
functions to work.
GET-OBSOLETE-VERSION class
returns the preceding obsolete version of this class, or NIL if none.
This allows users to define methods at any time on the obsolete class.
Obsolete classes themselves may also have an obsolete-version. Obsolete
classes also respond to
GET-UPDATED-VERSION obsolete-class
with the next class or NIL
This allows following the chain in the opposite direction
I don't have much objection to this. However, I don't see it as sufficient to
implement the goals you agreed upon. I see your proposal as a complement to
mine.
(let ((obsolete-class
(cdr (assoc class (GET-OBSOLETE-CLASSES-FOR-REDEFINITION class )))))
Add method on class-changes....
redefine the class class ...
(eq obsolete-class (GET-OBSOLETE-VERSION class)))
=> T
Patrick.
∂13-Jul-87 1039 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Metaclass Protocol Goals
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 13 Jul 87 10:39:10 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad17106; 13 Jul 87 13:12 EDT
Received: from ti-csl by RELAY.CS.NET id an13899; 13 Jul 87 13:05 EDT
Received: from Jenner by tilde id AA06513; Fri, 10 Jul 87 16:44:10 CDT
Message-Id: <2761940409-10490738@Jenner>
Date: Fri, 10 Jul 87 16:40:09 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Metaclass Protocol Goals
In-Reply-To: Msg of Thu, 9 Jul 87 13:30:59 pdt from Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Patrick's design rationale looks like a good beginning, and would be a good
addition to the beginning of 87-003, as motivation for the metaclass
protocol. I had a couple of comments and questions:
Thank you for your comments.
>Class behavior and instance behavior are othorgonal in CLOS. The
>metaclass protocol must preserve this orthoganality.
I'm not quite sure I understand what you mean by class and instance
behavior being orthogoal. Since class objects are instances of
the metaclass, this statement would seem not to be true for classes
when considered as instances.
What I meant is that the metaclass does affect the way classes parse their
defclass, compute class precedence list, gather their slots... all these things
are class business. On the other hand, it affects how instances are allocated,
laid out, accessed. That's instance business. These two sorts of businesses are
independent. I may want to keep a CLOS Syntax, CPL, etc, but have my instances
represented differently. I may want to define a FLAVOR metaclass and
represent its instances the way the default CLOS metaclass represents them.
>- The side effects on CLOS objects (Classes, generic-functions, methods)
>that spread across object links should be exposed.
>Compute-class-precedence-list is a good example.
I'm not sure I understand what you mean by "be exposed". What I
think you mean by "side effects on CLOS objects that spread across
object links" is protocols which affect objects whose structure acts
as templates for other objects (is that so?). As an example, the
structure of a class object acts as a template for instances. If
you mean that methods affecting the structure of such "template
objects" should be included in the public metaobject protocol, then
I agree.
Exposed means documented (what it is), with a protocol that goes with it (what
you can do, how you do it).
"Side effects on CLOS objects that spread across object links" means the side
effects that affect some other objects, not just the one you intended to
side-effect. For example, if you redefine a class, you are likely to affect
other classes besides the one you are redefining. These side effects are
particularly important to specify because they can spread across metaclasses.
If metaclass A handles class redefinition one way and metaclass B handles it in
a different way, then clearly we have a problem if we can mix classes of A with
classes of B.
>- It should be possible to access some exposed slots of a CLOS object
>without side-effect.
I agree with this, but I think it might be difficult to achieve in
practice. With method combination, it should be possible for the designer
of a metaclass to define a daemon method on any method in the protocol
which cause side effects to occur. I can think of a couple solutions to
this off the top of my head. One is to suggest that metaclass programmers
follow a convention of not defining daemon methods which cause side
effects, another is to specifically forbid defining daemon methods on
metaclass methods, possibly through a declaration mechanism (as I
suggested in an earlier note this spring). Probably the former is better,
since daemon methods for doing things like updating browsers when
classes are defined might be useful.
We define a protocol, not a language. A protocol is a set of rules that someone
must observe in order to preserve the integrity of the system. If we say "This
should be side effect free", it means that someone writing a new metaclass must
satisfy this constraint if he expect CLOS to continue working right. We
certainly don't want to do anything complicated to enforce it.
>- We probably need to care about the compile environment. We don't have
>to specify what it is but where, in our protocol it should be looked up
>or side effected. At least we must make sure that we don't go against
>the following statements:
>1)Compile-file does not side effect the running environment.
>2)It is possible to implement a cross loader (Something that loads files
>in order to make some class definitions, etc that will affect
>the compilation but not the running environment).
What I was trying to say here is we must define provision for implementations to
do a good job of defining a compilation environment, not to require it.
Using the PCLOS implementation from Gregor,
I tried a quick and dirty implementation of a seperate compile time
namespace for CommonObjects on CLOS and ran into some serious problems.
Running into problems because the implementation does not allow you to do it is
one thing, running into problems because the metaclass protocol makes it
impossible is another thing.
Patrick.
∂15-Jul-87 1000 kempf%hplabsz@hplabs.HP.COM Re: Class redefinition and class-changed.
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Jul 87 10:00:19 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Wed, 15 Jul 87 09:58:27 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Wed, 15 Jul 87 09:58:07 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Wed, 15 Jul 87 10:58:34 pdt
Message-Id: <8707151658.AA08774@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Your message of Fri, 10 Jul 87 10:00:21 CDT.
<2761916421-9049515@Jenner>
Date: Wed, 15 Jul 87 10:58:31 -0700
From: kempf%hplabsz@hplabs.HP.COM
> GET-OBSOLETE-VERSION class
> returns the preceding obsolete version of this class, or NIL if none.
> This allows users to define methods at any time on the obsolete class.
> Obsolete classes themselves may also have an obsolete-version. Obsolete
> classes also respond to
Is this meant to imply that there can be multiple versions of classes
floating about? If so, then perhaps class versioning needs to be
investigated more closely.
Jim Kempf kempf@hplabs.hp.com
∂16-Jul-87 0752 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 16 Jul 87 07:52:13 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab01711; 16 Jul 87 10:24 EDT
Received: from ti-csl by RELAY.CS.NET id ac00916; 16 Jul 87 10:17 EDT
Received: from Jenner by tilde id AA07022; Thu, 16 Jul 87 08:00:48 CDT
Message-Id: <2762427556-15862063@Jenner>
Date: Thu, 16 Jul 87 07:59:16 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of Wed, 15 Jul 87 10:58:31 -0700 from kempf%hplabsz@hplabs.hp.com
> GET-OBSOLETE-VERSION class
> returns the preceding obsolete version of this class, or NIL if none.
> This allows users to define methods at any time on the obsolete class.
> Obsolete classes themselves may also have an obsolete-version. Obsolete
> classes also respond to
Is this meant to imply that there can be multiple versions of classes
floating about? If so, then perhaps class versioning needs to be
investigated more closely.
I am not sure I agree with the term VERSION. An obsolete class object
is not a version of the class because it is here just to support the
class-changed protocol. It is not meant to have permanent instances.
Surrogate might be more appropriate. In the sense there can only be
instances of "current class" outside of the execution of CLASS-CHANGED,
I don't think we need to worry about class versioning.
Patrick.
∂22-Jul-87 0639 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 22 Jul 87 06:39:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa18126; 22 Jul 87 9:35 EDT
Received: from ti-csl by RELAY.CS.NET id ab14379; 22 Jul 87 9:31 EDT
Received: from Jenner by tilde id AA23150; Wed, 22 Jul 87 07:33:54 CDT
Message-Id: <2762944528-5369042@Jenner>
Date: Wed, 22 Jul 87 07:35:28 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Category Errors
In-Reply-To: Msg of 08 Jul 87 0938 PDT from Dick Gabriel <RPG@sail.stanford.edu>
From Gabriel:
One minor point that came up at the Symbolics meeting last Thursday
was category errors and whether we should try to outlaw them somehow.
Here is an example of a category error:
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
(make-instance (class-prototype (class-named 'apple-pie)) ...)
Here someone would be making a category error by defining a method on
MAKE-INSTANCE at the wrong level - the class level. What makes this easy
for a programmer to do this is the availability of CLASS-PROTOTYPE.
However, it is never hard to do because the programmer can write:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
to get his class prototype.
We have two alternatives:
1. Let sea of classes/metaclasses remain a miasma and inform
programmer that he ought not mix things up.
2. Define a notion of class category or classs level and have a
category of generic function for each class category.
From Ken Kahn:
I think it would be a mistake to build barriers between class and
metaclass protocols. One of the strong appeals of CLOS is that one can
experiment within its framework. We once worked out how Object Lisp's
view that classes and instances are pretty much the same could be
implemented in PCL. A good fraction of the OOP community believes in
these "prototypes" which unify classes and instances. We should be
careful not to prohibit CLOS from evolving in that direction if people
come to believe its a win.
I kind of agree with both Dick's and ken's concerns. The user should be
able to do metaclass programming if he wants to but this should be an
intent, not an accident. CLASS-PROTOTYPE working for standard-classes
is a good example of something intended to be used for metaclass
programming but works also for non metaclass classes.
I propose the following in order to categorize metaclass programming and
class programming:
CLASS
|
STANDARD-CLASS
|
METACLASS-CLASS
Now, all metaclass objects are instances of METACLASS-CLASS instead of
STANDARD-CLASS. This is to say that standard-class can be defined like:
(defclass STANDARD-CLASS (CLASS)
<slots>
(:metaclass METACLASS-CLASS))
STANDARD-CLASS does not support metclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
Somebody defining a new metaclass (or wanting to do metaclass
programming with his objects) will use METACLASS-CLASS as metaclass. It
will be a conscious decision.
The make-instance problem still exists but will not arise by accident,
somebody will have to do a trick like:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
and will probably get what he deserves.
Patrick.
∂22-Jul-87 1014 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jul 87 10:13:59 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 196114; Tue 21-Jul-87 12:35:38 EDT
Date: Tue, 21 Jul 87 12:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Jul 87 12:38 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870721123511.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 08 Jul 87 0938 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
I don't think this is fundamentally different from someone defining
a method on spaceships for a generic function that is only supposed to
be used with windows. The only reason I can see that confusion between
classes and metaclasses seems worse than confusion between spaceships
and windows is that metaclasses are less familiar.
If we didn't want to follow the usual Lisp philosophy of giving the
user enough rope to hang himself, we could add a feature such as the
following
(defgeneric-options make-instance (class &rest initargs)
(:parameter-specializer-restriction class (or class symbol)))
which says methods can't be defined with a parameter specializer for
the first parameter (named class) that isn't a subtype of (or class symbol).
Using the type system to express the restriction, rather than inventing
a new concept of levels, seems both more general and easier to understand.
However, I don't really think we want to add this kind of restriction, at
least, it wouldn't be consistent with the minimalist design criterion
we have used elsewhere in CLOS.
∂23-Jul-87 1812 Gregor.pa@Xerox.COM initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 18:12:34 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 23 JUL 87 18:11:32 PDT
Date: Thu, 23 Jul 87 18:09 PDT
From: Gregor.pa@Xerox.COM
Subject: initialization meeting notes
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
In this message I try to summarize what we agreed at the meeting in
Boston. The basis for this message is the 4 pages of notes which Sonya
took and which Sonya, Dave and I went over just before the meeting
ended. I have tried to include in this message only what we actually
agreed on. I will send out my comments and suggestions in a separate
message.
First, a brief summary of what we agreed:
- there will be a :initarg slot option
- will will support remote initarg defaulting by having an
defclass option like :default-initargs.
- there will be a procedural model of how the whole thing
works. Extensions to initialization behavior other than
simple-slot-filling-initargs and initarg-remote-defaulting
will be done by defining a method on the appropriate generic
function.
Another important thing which we agreed is that we are going to have to
go back and re-examine our rules for argument list congruence. The
existing rules clearly get in our way for doing initialization. In a
separate message I will try to summarize those problems.
In the meeting, we put up some code for make-instance and
initialize-instance. I am including that here:
(defmethod make-instance ((class-name 'symbol) &rest initargs)
(apply #'make-instance (class-named class-name) initargs))
(defmethod make-instance ((class standard-class) &rest initargs)
(let* ((proto (class-prototype class))
(defaulted-initargs (default-initargs proto initargs)))
(check-initargs class defaulted-initargs)
(let ((instance (apply #'allocate-instance class defaulted-initargs)))
(apply #'initialize-instance instance defaulted-initargs)
instance)))
(defmethod initialize-instance ((obj object) &rest initargs)
;; The default initialize-instance method deals with setting the
;; values of slots from slot-filling-initargs and from initforms.
;;
;; The rules are that the leftmost initarg which is declared
;; as setting a slot (with the :initarg slot option) actually
;; does set it (or is it the rightmost?); and that slots which
;; are not set by an initarg have their :initform evaluated and
;; used to set them.
)
An effect of putting the slot setting stuff in the default method on
initialize-instance is that most programmers will want to define their
initialize-instance methods as :after methods. This means an instance
will get initialized in order from most general to least general.
The default method for default-initargs implements the initarg remote
defaulting behavior using the :default-initargs class option.
The default method for check-initargs checks the validity of the
initargs by checking two sources:
1. an initarg is valid if it is specified as a slot-filling initarg.
2. an initarg is valid if it is specified as a &key argument in
one of the applicable methods on initialize-instance.
Here is an example of a use of this protocol:
(defclass ship ()
((x :initarg :x)
(y :initarg :y)))
(defmethod initialize-instance :after ((s ship) &key startp)
(when startp (start s)))
(defmethod start ((s ship))
(with-slots ((s :use-accesors nil))
(if (and x y)
<start it up>
(error "Have to set X and Y before starting a ship."))))
(defclass homing-ship (ship)
()
(:default-initargs
:x 0
:y 0))
(defmethod home ((s homing-ship))
(with-slots ((s :use-accessors nil))
(setq x 0 y 0)))
We also agreed that there would be documented functions for finding out
about the initargs that set slots for a class and also finding out about
the default initargs for a class. This doesn't seem to be too hard;
the only serious problem has to do with arranging for a the default
initarg value forms to be evaluated in the lexical environment of the
defclass. (Of course if environments were first class objects this would
be trivial...)
-------
∂23-Jul-87 1917 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 19:16:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JUL 87 19:16:02 PDT
Date: 23 Jul 87 19:15 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 21 Jul 87 12:35 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870723-191602-1486@Xerox>
I don't think this is fundamentally different from someone
defining a method on spaceships for a generic function that is only
supposed to be used with windows. The only reason I can see that
confusion between classes and metaclasses seems worse than
confusion between spaceships and windows is that metaclasses are
less familiar.
I think this is exactly right.
If we didn't want to follow the usual Lisp philosophy of giving
the user enough rope to hang himself,
Leave the rope. We don't put strong typing in Lisp either.
danny
∂23-Jul-87 1941 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 19:41:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JUL 87 19:41:10 PDT
Date: 23 Jul 87 19:41 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 10 Jul 87 10:00:21 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870723-194110-1523@Xerox>
The necessary and sufficient condition for this is to
be able to get hold of an obsolete version of a class.
I don't agree. We said in chapter 1 that the updating of the
instances is done at an implementation-dependent time.
I agree that your arguments imply your conclusion. I think however,
that it would be better to say that "updating of the
instances is done at an implementation-dependent time sometime after the
class is redefined." Since this is really an environment support
feature, I think we should specify that it will not occur before the
first method on an obsolete instance is called.
danny
∂24-Jul-87 0623 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 06:23:14 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa05351; 24 Jul 87 9:23 EDT
Received: from ti-csl by RELAY.CS.NET id aa06359; 24 Jul 87 9:16 EDT
Received: from Jenner by tilde id AA01610; Fri, 24 Jul 87 07:33:49 CDT
Message-Id: <2763117294-15749125@Jenner>
Date: Fri, 24 Jul 87 07:34:54 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 23 Jul 87 19:41 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
I agree that your arguments imply your conclusion. I think however,
that it would be better to say that "updating of the
instances is done at an implementation-dependent time sometime after the
class is redefined." Since this is really an environment support
feature, I think we should specify that it will not occur before the
first method on an obsolete instance is called.
I see two problems with this approach:
- How would the environment guess that a class-changed method will (or will not)
be defined?
- Even if you see it as an environment support, we need to specify this support
at the metaclass level since class redefinition will be specified. I don't think
we can afford to leave holes like that in the metaclass protocol.
Patrick.
∂24-Jul-87 0854 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Jul 87 08:54:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 JUL 87 08:51:47 PDT
Date: 24 Jul 87 08:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 24 Jul 87 07:34:54 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870724-085147-2517@Xerox>
I think we should specify that instance updating will
not occur before the first method on an obsolete instance is
called.
I see two problems with this approach:
- How would the environment guess that a class-changed method
will (or will not) be defined?
It doesn't have to guess. If the class changed method is defined before
any any method is called on an obsolete instance, it will be used.
Otherwise not. Hence users should define such class-changed methods
immediately (soon) after redefining the class.
- Even if you see it as an environment support, we need to
specify this support at the metaclass level since class
redefinition will be specified. I don't think we can afford to
leave holes like that in the metaclass protocol.
The meta-object support necessary is to provide a mechanism to obtain
the obsolete class so that class-changed methods can be defined, and to
specify when these methods can be defined in order to effect all
instances that need to be updated.
danny
∂24-Jul-87 1133 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 11:33:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198616; Fri 24-Jul-87 14:34:24 EDT
Date: Fri, 24 Jul 87 14:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2762944528-5369042@Jenner>
Message-ID: <870724143345.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 22 Jul 87 07:35:28 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
....
I propose the following in order to categorize metaclass programming and
class programming:
CLASS
|
STANDARD-CLASS
|
METACLASS-CLASS
Now, all metaclass objects are instances of METACLASS-CLASS instead of
STANDARD-CLASS. This is to say that standard-class can be defined like:
(defclass STANDARD-CLASS (CLASS)
<slots>
(:metaclass METACLASS-CLASS))
I believe this is a good suggestion. That is, it appeals to my aesthetic
sense, although I have not been able to come up with any specific programming
activities that require it.
STANDARD-CLASS does not support metaclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
This part, however, won't work. As I understand it, CLASS-PROTOTYPE has
to work on all classes, because of the way the generic function dispatching
in the initialization protocol is going to work. We still haven't nailed
down the initialization protocol, but I think the part of it we all seem
to agree on already requires all classes to have a prototype.
Similarly, functions like CLASS-DIRECT-SUPERCLASSES are part of metaclass
programming, but that doesn't mean they are only applicable to metaclasses.
They are applicable to all classes.
∂24-Jul-87 1136 RPG Category Errors
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``I don't think this is fundamentally different from someone defining a
method on spaceships for a generic function that is only supposed to be
used with windows.''
Danny replies:
``I think this is exactly right.''
As I mentioned in my note, I don't care that this blemish appears in CLOS,
but I do insist that we understand that reasonable people will consider it
to be a blemish. The reason for this is also the reason that Danny's reply
is incorrect. The differences between someone writing a method on
spaceships for a generic function that is only supposed to be used with
windows and someone writing a method on a base-level class for the generic
function MAKE-INSTANCE are these:
1. MAKE-INSTANCE is a generic function defined in CLOS, and we
have the ability to enforce the user not making this sort of
error. We've carefully laid out, in most cases, the range of
legal arguments to functions and generic functions in CLOS; we
could easily do that here, whereas it's difficult to control a
user who wants to act irrationally with code all of his own
invention.
2. Mistakenly writing methods for some class not intended to be
the subject of the generic function by the author of that
generic function is most likely a user-level semantic error,
while defining a method on a class where the person defining
the generic function intends methods to be on meta-classes is a
category error - that's why I called it a ``category error''
rather than a ``source of potential user bugs.'' The error lies
in confusing two levels of classes defined in CLOS rather than
in confusing two classes defined by a user.
My point was that one could rationally design CLOS to be able to
distinguish between classes and meta-classes, and hence we would be
justified in trying to prevent category errors. Or we could choose not to
do that. I think that to dismiss the point as some fluke in thought
process before understanding the issues does ill justice to the
specification process, even though I believe we will allow the blemish.
-rpg-
∂24-Jul-87 1420 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:20:00 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 JUL 87 14:19:44 PDT
Date: 24 Jul 87 14:19 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 24 Jul 87
11:36 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870724-141944-3247@Xerox>
My point was that one could rationally design CLOS to be able
to distinguish between classes and meta-classes, and hence we would
be justified in trying to prevent category errors.
If it were clear that one could be sure that a definition were in error,
then perhaps we could consider enforcing some restrictions. However, it
is a rational thing to experiment with various new types of object
system, defining methods for all the protocol of interest, and not use
any preexisting class as a super-class (this is particularly a good idea
if one wants to make sure that the new implementation is complete). To
force a user to use a particular (perhaps empty) metaclass just for a
declaration surely violates the spirit of Lisp.
We've carefully laid out, in most cases, the range of
legal arguments to functions and generic functions in CLOS; we
could easily do that here, whereas it's difficult to control a
user who wants to act irrationally with code all of his own
invention.
We have NOT laid out the range of legal arguments for generic functions.
We have specified how they behave for arguments of particular classes;
tha is, we have described some method(s) on generic functions, and their
contract. A major point of object oriented programming is to allow
users to add their own methods to generic functions. To talk about THE
AUTHOR OF A GENERIC FUNCTION is to make the same mistake. Generic
functions have certain contracts, but not ones that restrict them to
certain classes of arguments.
I think that to dismiss the point as some fluke in thought
process before understanding the issues does ill justice to the
specification process, even though I believe we will allow the
blemish.
I think understanding the issue is important. So we agree on that
point. But I feel that the "blemish" is really a beauty mark.
danny
∂24-Jul-87 1421 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:21:16 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa10495; 24 Jul 87 17:10 EDT
Received: from ti-csl by RELAY.CS.NET id al08816; 24 Jul 87 17:04 EDT
Received: from Jenner by tilde id AA14079; Fri, 24 Jul 87 15:14:43 CDT
Message-Id: <2763144693-1137879@Jenner>
Date: Fri, 24 Jul 87 15:11:33 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: DUSSUD%Jenner%ti-csl.CSNet@RELAY.CS.NET,
common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 24 Jul 87 08:48 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
Date: 24 Jul 87 08:48 PDT
From: Danny Bobrow <Bobrow.pa@xerox.com>
Subject: Re: Class redefinition and class-changed.
It doesn't have to guess. If the class changed method is defined before
any any method is called on an obsolete instance, it will be used.
Otherwise not. Hence users should define such class-changed methods
immediately (soon) after redefining the class.
In multiprocessing or interruptible environment, immediately is a weak
concept at best. You might get in a race condition with another
computation unit that touches instances. Furthermore, you can't prove
that some instances haven't been updated before you define the
changed-class method. How do you propose to solve this?
Patrick.
∂24-Jul-87 1427 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:22:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah10487; 24 Jul 87 17:10 EDT
Received: from ti-csl by RELAY.CS.NET id am08816; 24 Jul 87 17:04 EDT
Received: from Jenner by tilde id AA14334; Fri, 24 Jul 87 15:24:33 CDT
Message-Id: <2763145381-1179246@Jenner>
Date: Fri, 24 Jul 87 15:23:01 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Category Errors
In-Reply-To: Msg of Fri, 24 Jul 87 14:33 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
STANDARD-CLASS does not support metaclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
This part, however, won't work. As I understand it, CLASS-PROTOTYPE has
to work on all classes, because of the way the generic function dispatching
in the initialization protocol is going to work. We still haven't nailed
down the initialization protocol, but I think the part of it we all seem
to agree on already requires all classes to have a prototype.
This is true, I forgot about it when I wrote this part.
Patrick.
∂24-Jul-87 1436 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:36:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198754; Fri 24-Jul-87 16:44:25 EDT
Date: Fri, 24 Jul 87 16:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: initialization meeting notes
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Message-ID: <870724164346.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
There's a bunch of other stuff in the notes that didn't make it into
your message. Perhaps I'll send a summary of that in a later message,
but the most important thing right now from my point of view was a
statement (page 4) about open-coding which I think means that the
procedural model is to be done in such a way that it does not decrease
achievable performance of creating instances; in particular, the system
is allowed to recognize that the standard methods are being called for
make-instance of a particular class and use a different implementation
that produces equivalent results. This will have to be defined in more
precise language in the final specification, so that it is quite clear
what users can and cannot depend on.
∂24-Jul-87 1437 Moon@STONY-BROOK.SCRC.Symbolics.COM First Try at Terminology
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:36:59 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198777; Fri 24-Jul-87 17:02:52 EDT
Date: Fri, 24 Jul 87 17:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: First Try at Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Jul 87 12:28 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870724170213.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I might quibble with one or two details, in particular the idea that it
is possible to prevent programmers from discovering and depending upon
what a particular implementation does in a particular undefined
situation, however on the whole this seems pretty good. I'd like to
see the terminology for erroneous situations tightened up for all of
Common Lisp, not just CLOS.
I don't think that it's the business of the CLOS subcommittee to do this.
In other words, I'm uncomfortable with the idea that "the CLOS
subcommittee of X3J13 is the only subcommittee that ever does anything"
(incidentally this is not quite true) implies that "the CLOS
subcommittee should do everything."
We can use a working terminology in our deliberations, but we should
be prepared to convert to whatever standard terminology is defined for
Common Lisp as a whole, when that happens. This suggests that we should
do something fairly simple and not develop an elaborate formalism.
Simply separating the cases of "an error is always signalled", "an error
is signalled unless you tell the compiler not to check for it", "the
effect is undefined", and "the effect is implementation-dependent"
seems sufficient to me.
∂24-Jul-87 1459 RPG Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
Danny says:
``We have NOT laid out the range of legal arguments for generic functions.''
My comment was:
``We've carefully laid out, in most cases, the range of legal arguments to
functions and generic functions in CLOS....''
I guess I shouldn't rely on subtle wording to get across a subtle point.
Here is a generic function ``in CLOS'':
Add-method generic-function method
And here is how we have ``carefully laid out ... the range of legal
arguments'' to it:
Arguments:
The generic-function argument is a generic function
object.
The method argument is a method object. The
lambda-list of the method function must be
congruent with the lambda-lists of any other
methods associated with the generic function and
with the lambda-list of the generic function.
(page 2-5, FUNCTIONS)
The thing in CLOS that is already the same sort of ``blemish'' as this
category error is discrimination on individuals. Blemish, beauty mark:
At least we can agree that in both cases an observer is justified in
thinking ``what's that thing?''
-rpg-
∂24-Jul-87 1645 RPG Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
The problem with class redefinition is that the updating of instances can
be caused by arbitrary events, as far as the user is concerned. If none of
DEFCLASS, ADD-METHOD, MAKE-METHOD, CLASS-NAMED, the evaluation of the
special form FUNCTION, and garbage collection can update instances, then
if a CLOS implementation does not have multitasking, the following will
work (or something like it):
(let ((obsolete-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,(class-named 'heh-heh))
#'...)))
If there is a CLOS implementation with all of the properties named
above except it does have multitasking (including incremental GC),
then some form or macro like ATOMICALLY wrapped around the above
will work.
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
I think, though, that it probably makes sense to have Danny's version
of GET-OBSOLETE-CLASS for the same reason that I don't like UNIX - it's
too easy to do a DEFCLASS of an existing class and then wish you
had a handle on the old one. I think we need to decide whether Patrick's
versions of getting obsolete classes are worth having around to simplify
life.
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
-rpg-
∂25-Jul-87 0719 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jul 87 07:19:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198981; Fri 24-Jul-87 22:34:00 EDT
Date: Fri, 24 Jul 87 22:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Category Errors
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 14:36 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870724223320.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
As a believer in open systems who doesn't think there should be distinctions
between system and user programs, I believe that Dick's arguments for defense
against defining bogus methods for MAKE-INSTANCE are equally as good
arguments for defense against defining bogus methods for any user-defined
generic function. Remember that not all user-written programs are used only
by their author.
Dick, would you agree that if CLOS removes this blemish, it should be done
with a mechanism that is easily accessible to the programmer-in-the-street?
My second point was that although I favor removing this blemish, CLOS currently
contains several other similar blemishes added in the name of simplicity
(example, no equivalent to Flavors' :required-methods defflavor option), so
I predict that we will end up leaving this blemish in. That's not an argument,
just an observation.
∂25-Jul-87 0720 Moon@STONY-BROOK.SCRC.Symbolics.COM Class redefinition and class-changed.
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jul 87 07:20:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198991; Sat 25-Jul-87 01:27:15 EDT
Date: Sat, 25 Jul 87 01:26 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class redefinition and class-changed.
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2761765326-16486571@Jenner>,
<870709-115412-4166@Xerox>,
<2761916421-9049515@Jenner>,
<8707151658.AA08774@hplabsz.hpl.hp.com>,
<2762427556-15862063@Jenner>,
<870723-194110-1523@Xerox>,
<2763117294-15749125@Jenner>,
<870724-085147-2517@Xerox>,
<2763144693-1137879@Jenner>
Message-ID: <870725012629.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have several comments to offer on this conversation. I haven't managed
to organize the separate comments into as coherent a whole as I would like.
I believe Patrick's argument that it is necessary to define the
CLASS-CHANGED method -before- redefining the class. Symbolics has a lot of
experience with doing it the other way and it's unpleasant. I hope the
reasoning for this has been established now and doesn't need additional
argument (Danny, please speak up if you don't believe it yet).
I don't like Patrick's particular proposal, though.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is too complicated, because it
returns a whole alist rather than being just the primitive. In addition, I
don't think the set of "classes implicated in the class-redefinition of
CLASS" is computable until the details of the redefinition are known.
Suppose
(defclass one () (a b))
(defclass two (one) (c))
(defclass three (one) (d))
Now suppose we redefine one as follows:
(defclass one () (a b d))
Referring to the third paragraph on page 1-11 of 87-002, one and two are
"implicated", but three is not, or at least, whether three is implicated is
implementation-dependent. But if the new slot had been named e, both two
and three would have been implicated. I don't think the information in
Patrick's alist is needed anyway; when defining a method, one only defines
it for the obsolete class corresponding to one class. If a different
method needs to be defined for an obsolete subclass, the function can be
called again.
Thus I would replace Patrick's proposal with GET-OBSOLETE-CLASS-FOR-REDEFINITION
which takes one argument, a class, and returns one value, the obsolete class
that is a copy of the current definition of the class and will be used the next
time the class is redefined; this is created the first time you ask for it.
Perhaps GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION would be a better name.
As Danny proposed, a primitive to get the obsolete classes corresponding to
redefinitions that have already taken place is useful, for instance in case
you didn't realize ahead of time that you would need a CLASS-CHANGED method
and now want to patch up the program. I would suggest a function
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS which takes one argument, a
class, and returns one value, a list of obsolete classes, newest first.
There seems to be some confusion about how class redefinition works in CLOS
and what an "obsolete class" is. Let me restate what the 87-002 document
says in simpler language: Redefining a class never creates a new class
object to replace the existing class object; it always modifies the
existing class object. Thus there are no objects that exactly represent
"versions" of a class. There is also the concept of "obsolete instances",
which have dynamic extent and are created solely to pass as the first
argument to CLASS-CHANGED. When CLASS-CHANGED is called as a result of the
user calling CHANGE-CLASS, the obsolete instance is simply an instance of
the old class. When CLASS-CHANGED is called as a result of updating an
instance to reflect the latest definition of its class, the obsolete
instance contains the slot values of the un-updated instance and therefore
needs to have a class that has those slots: this is an "obsolete class".
An obsolete class is a copy of a class remembering the slots, methods, and
superclasses it had before it was redefined. Redefining a class only
creates an obsolete class when certain kinds of changes are made to the
class (see the third paragraph on page 1-11 of 87-002). For each past
version of a class that is sufficiently different from the current version,
there is an obsolete class object. Note that these are all obsolete versions
of the original class, they are not obsolete versions of each other.
Redefining a class also redefines subclasses of the class, so several
obsolete classes could be created. 87-002 doesn't say so, but I believe
the obsolete subclasses should be subclasses of the obsolete class and not
of the original class.
The second paragraph on page 1-12 of 87-002 could be interpreted as saying
that the only methods that are applicable to an obsolete instance I-sub-O
are the methods M-sub-C that were deleted from the class when it was
redefined. I do not believe this is what was intended--I believe we
intended to say that all methods that were applicable to instances of the
class before it was redefined are applicable to I-sub-O (unless additional
redefinitions have been done, for instance deleting those methods
entirely). If we really intended only deleted methods to be applicable, it
would be remarkably useless: for instance, deleted slots could be accessed
by normal means, but non-deleted slots could not be accessed except by
SLOT-VALUE, except in the case where the :ACCESSOR slot-option had been
removed. Again, in the x-y-rho-theta example, if methods for accessing
values that are conceptually slots but are not physically represented as
slots were not applicable, it would be necessary to violate modularity and
duplicate the functionality of those methods within the CLASS-CHANGED
method.
We have our choice of three ways to define what happens when a class is
redefined:
(1) A new class object is created, the name-to-class-object mapping is
changed, defclass-defined methods implied by the new definition are put on
the new class object, all methods other than defclass-defined methods that
apply to the old class are made to apply also to the new class, subclasses
of the old class are made to be subclasses of the new class instead, and
superclasses of the old class are made to be also superclasses of the new
class. If we had done this, there would have been an explicit
representation of versions of a class, and there would not have been any
concept of "obsolete classes."
(2) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, an anonymous obsolete class object is created, the modification is
propagated to subclasses which may create obsolete class objects for them
that are subclasses of the first obsolete class created, superclasses of
the original class are to be also superclasses of the obsolete class, and
all methods that applied to the original class are made to apply also to
the new class. (2) is what we did in 87-002. (2) is not simpler than (1),
but it has the advantage that classes maintain their identity as objects.
(3) There is a third way, which I will describe later in this message.
Referring again to the third paragraph on page 1-11 of 87-002, there is
another use for a primitive to get the obsolete class before redefining the
class. Not all redefinitions of a class call CHANGE-CLASS and
CLASS-CHANGED. Suppose someone changes a class in such a way that they
need to call a function to update each instance, but they have not actually
add, removed, or renamed slots. 87-002 does not provide any mechanism for
this. The programmer would probably resort to adding a dummy slot to force
instance updating. I think a better approach would be to specify that
calling GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION forces the next
redefinition of this class (directly or by redefining a superclass) to
update instances, even if it would not otherwise need to.
There are basically three approaches to the problem of writing a
CLASS-CHANGED method that updates an instance to reflect one particular
edit of the class's definition:
(1) Use the classes of the two arguments to CLASS-CHANGED to encode this
information. This is what the 87-002 document says, however it doesn't work.
(2) Use a third argument to CLASS-CHANGED to encode the information, such as
a sequence number saying how many times the class had been redefined. This
seems kludgey and was rejected in the past.
(3) Don't allow such precise control over instance updating in CLOS, instead
only allow CLASS-CHANGED methods that work for updates from -any- version of
the class to the current version. This is copping out, however it's practical,
since it's what Flavors does.
There are two reasons (1) doesn't work. First, 87-002 doesn't provide a way
to get the obsolete class for a particular edit, which you need in order to
define a method that applies specifically to that edit. This is what Patrick's
proposal addresses. Second, there is a problem when the class is redefined
multiple times. Suppose we do
(defclass foo () (a))
(defclass foo () (a b))
(defclass foo () (a b c))
(defclass foo () (a b c d))
and in connection with the third definition we need a CLASS-CHANGED method
to initialize the slot C. We don't want this method to be called for
instances that already have a slot C and are getting a slot D added, so we
want the method to specialize its first parameter as well as its second.
The problem is that CLOS has no way to define one method that applies to the
first and second obsolete classes, but not to the third obsolete class. In
order to define this method, we have to know the exact editing history of
the class FOO, which seems unreasonable. We can't fix this by making the
second obsolete class a subclass of the first obsolete class, because if
the user removes a slot we would have a class that has fewer slots than its
superclass, which CLOS does not allow. We could call
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS to get the entire list of
obsolete classes for the class FOO, and then we could iterate over that
list seeing which obsolete classes had a slot C and which didn't, and
define CLASS-CHANGED methods accordingly, but this starts to look like an
elaborate rigamarole for something that should have been simple.
The above assumes that we believe what page 1-12 of 87-002 implies, namely
that instances are updated directly to the latest version of the class
("the second argument is an instance of the class C"). Alternatively, we
could specify that "ontogeny recapitulates phylogeny" and the instance is
repeatedly updated one step at a time, until it reaches the current
definition of its class. In the FOO example above, we would define the
CLASS-CHANGED method that initializes C to specialize its first parameter
to the second obsolete class, with confidence that instances of the
original FOO would first get a slot B, then would get a slot C, then would
get a slot D, and in the second of the three steps, our method would be
called.
This means that -both- arguments to CLASS-CHANGED could be instances of
obsolete classes. It also means that our CLASS-CHANGED method can't
specialize its second parameter, because at first that will be the class
FOO, but after FOO is redefined again, it will be an obsolete class. If we
don't specialize the second parameter, it seems we could be confused by
CLASS-CHANGED being called when CHANGE-CLASS was used to change an instance
of FOO into an instance of BAR. This is not a problem if CHANGE-CLASS,
like all other generic functions, first updates its argument to the latest
definition of its class, before changing it to the new class; then a method
specialized to an obsolete class in its first parameter can never be called
with the second parameter an instance of anything other than the next newer
version of the same class. This all seems slightly kludgey, but does seem
like it should work.
Is there any chance of garbage collecting all these obsolete classes when
there are no longer any instances that haven't been updated yet? We'd also
like to garbage collect the data structures required to make methods
applicable to the original class also applicable to the obsolete class.
I doubt it's possible to GC this stuff, the whole data structure seems too
interconnected.
The third way to define what happens when a class is redefined, mentioned
earlier, is as follows: Don't try to use CLASS-CHANGED for both changing
the class of an instance and updating an instance to a new version of its
class. Invent a new generic function CLASS-REDEFINED, which is called when
an instance is updated to a new version of its class. This avoids the
complicated concept of "obsolete classes", at the cost of conveying the
former state of the instance in a less object-oriented fashion. Perhaps
CLASS-REDEFINED would receive three arguments: an instance of the class,
already updated to the latest definition of the class, a property list
associating slot names to slot values, with one entry for each slot that is
no longer present, and a list of slot names of slots that were newly added
to the instance. Thus when a class is redefined:
(3) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, and the modification is propagated to subclasses. This is simpler
than (1) or (2).
The FOO example given above is implemented by defining a CLASS-REDEFINED
method that checks whether slot C is a new slot before initializing it.
The problem is that there can only be one CLASS-REDEFINED method, since
there is only one class object, so if the class is redefined multiple times
in ways that need CLASS-REDEFINED methods, this one method must contain
unmodular knowledge of all the redefinitions. In addition, in the
x-y-rho-theta example, if there are methods for accessing values that are
conceptually slots but are not physically represented as slots, the
CLASS-REDEFINED method has to know about the underlying slots used by
these methods, in case those slots have been deleted.
This "third way" seems simpler than the other two, so I hope that someone
can debug the problems mentioned in the previous paragraph. If not, we
need to make several changes mentioned here and there in this message in
order to make obsolete classes work.
∂27-Jul-87 0930 kempf%hplabsz@hplabs.HP.COM Re: Class Redefinition
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 09:29:49 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Mon, 27 Jul 87 09:28:47 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Mon, 27 Jul 87 09:28:24 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Mon, 27 Jul 87 09:26:23 pdt
Message-Id: <8707271526.AA11550@hplabsz.hpl.hp.com>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class Redefinition
In-Reply-To: Your message of 24 Jul 87 16:45:00 -0700.
Date: Mon, 27 Jul 87 09:26:20 -0700
From: kempf%hplabsz@hplabs.HP.COM
>
> (name-that-class new-class 'heh-heh)) ;Hm, what is this function
?
> I think we forgot to de> f> ine NAME-THAT-CLASS. It should be the thing such
> that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
Something like:
(setf (class-name new-class) 'heh-heh)
should work. The name is not listed as a slot in STANDARD-CLASS in the
87-003 metaobject protocol, however.
jak
------- End of Forwarded Message
∂27-Jul-87 0933 kempf%hplabsz@hplabs.HP.COM Technical corrections in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 09:32:43 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Mon, 27 Jul 87 09:31:19 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Mon, 27 Jul 87 09:30:46 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Mon, 27 Jul 87 07:45:32 pdt
Message-Id: <8707271445.AA11199@hplabsz.hpl.hp.com>
To: rpg@SAIL.STANFORD.EDU
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, olthoff@hplabsz.hpl.hp.com,
kempf@hplabsz.hpl.hp.com
Subject: Technical corrections in 87-002
X-Mailer: mh6.5
Date: Mon, 27 Jul 87 07:45:28 -0800
From: kempf%hplabsz@hplabs.HP.COM
Dick:
Apologies if this arrives more than once. Our mail system is
changing.
The formal specification of method application and combination
is completed, and a couple of omissions, typos, and other
technical errors were found. While I agree with Moon that it probably
isn't a good idea to inject a level of formalism into CLOS beyond that
customary for the Common Lisp community, I hope that the results of
work from those who are interested in such formalism can be fed back
into the design process, in the spirit of trying to make the CLOS
specification as precise as possible.
Here are the corrections:
1) The use of the term "partial order" on pg. 1-15, paragraph 1 implies
a relation on R which is reflexive, antisymmetric, and transitive. From the
text of the paragraph, this relation is presumably the "is a subclass of"
relation. However, earlier in the document, reflexivity is explicitly
excluded from the "is a subclass of" relation (pg. 1-4, paragraph 3),
since a class is defined to be neither a superclass nor a subclass
of itself. Either the partial order needs to be replaced
with a different order not requiring reflexivity (semiorder, etc.)
or the "is a subclass of" relation needs to be redefined
so that it is reflexive. Note that the latter solution is used in more
technical treatments of typing systems (e.g. Cardelli and Wegner, Computing
Surveys, 17, 1985, pp. 471-522).
2) As noted in the followup to my posting of the preliminary formal
specification for method applicaton and combination, the phrase "either
method may precede the other" on p. 1-21, last paragraph is not technically
correct, since the two methods are incomparable with regard to precedence. The
algorithm is nevertheless sound, because it describes sorting of method
equivalence classes rather than methods, and precedence between equivalence
classes, so the ordering of elements in a specific equivalence class is
arbitrary.
3) With reference to my original posting, the case of both specializers
being quoted objects cited on pg. 1-22, paragraph 3 cannot occur at that
point in the algorithm. Either one or the other can be a quoted object,
but since , by that point in the algorithm: a) the two methods
being compared must differ on the parameter specializer, and, b) in
order for a method to be applicable at all and the specializer to be
a quoted object, the specializer must be EQL to the parameter, this
condition cannot occur.
4) The formal description of class precedence list calculation on pg. 1-15,
paragraph 3 is lacking a condition. In the third line, it is not sufficient
just to require the existence of an index i, but also its minimality.
As a counterexample, consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4 c6)}
The inheritance graph for this is;
c5 c6
| |
c3 c4
| |
\ /
\ /
c2
|
c1
In the first step, cpl := [c1] and R := R\{(c1,c2)}, where A\B denotes
the set A with all elements of A INTERSECT B removed (quotient set).
Next step: cpl := [c1 c2] and R := {(c2,c3) (c2,c4)}. Now the set of
classes without predecessors is {c3 c4}. Then, according to the
description of the algorithm on pg. 1-15 paragraph 3, j=2 is the
largest number such that "there exists i=3 with c3 being the direct
superclass of c2," but i=4 also holds with this property, so it
cannot be determined whether c3 or c4 should be added to the class
precedence list. Requiring the minimal i to be used will remove
the ambiguity, in the example, making c3 the next element of the cpl.
I hope these corrections can be added to the next draft of the
CLOS document.
Jim Kempf kempf@hplabs.hp.com
∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Name That Class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:01:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 199633; Mon 27-Jul-87 12:53:29 EDT
Date: Mon, 27 Jul 87 12:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 19:45 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870727125306.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
I thought CLASS-NAMED was SETF'able, but 87-002 doesn't say so. Should
we change that?
∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:01:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 199639; Mon 27-Jul-87 12:58:38 EDT
Date: Mon, 27 Jul 87 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 19:45 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870727125813.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
....
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
This doesn't conform to 87-002's specification that redefining a class
updates the existing class object, rather than replacing it with a new
class object. Indeed, if we changed that, we wouldn't need the concept
of "obsolete classes", as I pointed out in my message of early Saturday
morning (sent after you wrote this message, but before I saw your message;
we've had a lot of network problems lately, first with window-caulkers
parking their scaffolding in the middle of the through-the-air segment
of our network for a week, then MIT air conditioning failure, and who
knows what else.) However, because methods are classified by class
objects rather than class names, replacing the old class object with a
new one has its own complexities.
∂27-Jul-87 1046 Bobrow.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:46:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JUL 87 10:46:00 PDT
Date: 27 Jul 87 10:45 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Name That Class
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 12:53 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
Message-ID: <870727-104600-1451@Xerox>
I thought CLASS-NAMED was SETF'able, but 87-002 doesn't say so.
Should we change that?
Yes.
danny
∂27-Jul-87 1159 RPG Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
(setf (class-named ...) ...) is good.
-rpg-
∂27-Jul-87 1224 RPG Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon says: <your code won't work>.
I know that the specification states that my code won't work, but
many folks (and not unsophisticated ones) will think it should.
It would be nice if different classes weren't EQ. Is there no way to
make this work? Isn't it true that the only place we need to have
a class and its redefined class be the same is within method selection,
and can't we use surrogates there?
-rpg-
∂27-Jul-87 1700 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class Redefinition
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Jul 87 17:00:15 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad05828; 27 Jul 87 17:02 EDT
Received: from ti-csl by RELAY.CS.NET id aw25936; 27 Jul 87 16:51 EDT
Received: from Jenner by tilde id AA12921; Mon, 27 Jul 87 09:16:28 CDT
Message-Id: <2763382458-15423174@Jenner>
Date: Mon, 27 Jul 87 09:14:18 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class Redefinition
In-Reply-To: Msg of 24 Jul 87 1645 PDT from Dick Gabriel <RPG@sail.stanford.edu>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@sail.stanford.edu>
Subject: Class Redefinition
The problem with class redefinition is that the updating of instances can
be caused by arbitrary events, as far as the user is concerned. If none of
DEFCLASS, ADD-METHOD, MAKE-METHOD, CLASS-NAMED, the evaluation of the
special form FUNCTION, and garbage collection can update instances, then
if a CLOS implementation does not have multitasking, the following will
work (or something like it):
(let ((obsolete-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,(class-named 'heh-heh))
#'...)))
This code is not quite right, the new class object (produce by defclass
heh-heh is the same as the old one (the one you bound to
obsolete-class). [pg 1-11]
The following will work.
(let ((current-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,(get-obsolete-version current-class) ,current-class)
#'...)))
If there is a CLOS implementation with all of the properties named
above except it does have multitasking (including incremental GC),
then some form or macro like ATOMICALLY wrapped around the above
will work.
Right. However, the CPU time spent in ATOMICALLY can be quite
large, realistically some implementation will not be able to give an
upper bound for its elapsed time from start to completion. If a CLOS
implementation has to make sure that this time is kept short, it will
have to bear yet another constraint that could be avoided.
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
This does not work for the same reason the first example did not work.
However I don't see how to fix this one without resorting to my
proposal. It would go like this:
(let*
((current-class (class-named 'heh-heh))
(obsolete-class (assoc current-class
(GET-OBSOLETE-CLASSES-FOR-REDEFINITION
current-class))))
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,current-class)
#'...))
(defclass heh-heh ...)) ;(name-that-class new-class 'heh-heh))
I think, though, that it probably makes sense to have Danny's version
of GET-OBSOLETE-CLASS for the same reason that I don't like UNIX - it's
too easy to do a DEFCLASS of an existing class and then wish you
had a handle on the old one. I think we need to decide whether Patrick's
versions of getting obsolete classes are worth having around to simplify
life.
If you can find another solution to your second example (ie without
using ATOMICALLY), I would be inclined to live with Danny's
proposal.
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
This thing will be in the metaclass protocol
Patrick.
∂27-Jul-87 1905 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 19:05:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 200139; Mon 27-Jul-87 22:06:01 EDT
Date: Mon, 27 Jul 87 22:05 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: initialization meeting notes
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Message-ID: <870727220545.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 23 Jul 87 18:09 PDT
From: Gregor.pa@Xerox.COM
In this message I try to summarize what we agreed at the meeting in
Boston.
Thanks for getting all this on-line. I see only two things to disagree
with here, so we should start putting our heads down and agreeing on the
next level of detail.
(defmethod initialize-instance ((obj object) &rest initargs)
;; The default initialize-instance method deals with setting the
;; values of slots from slot-filling-initargs and from initforms.
;;
;; The rules are that the leftmost initarg which is declared
;; as setting a slot (with the :initarg slot option) actually
;; does set it (or is it the rightmost?); and that slots which
;; are not set by an initarg have their :initform evaluated and
;; used to set them.
)
It's leftmost, because that's the way duplicated &key arguments work
in all other Common Lisp functions.
Actually there are two issues here:
(1) If the same initarg appears more than once in the initargs list,
the leftmost occurrence is used and later occurrences are ignored.
This is just consistency with &key and there's really no choice.
(2) If more than one initarg is defined to fill a given slot, and more
than one of these initargs appears in the initargs list, what happens?
Flavors takes the rightmost, but that's a misfeature. We should either
signal an error or take the leftmost. It's a one-line change to make
Flavors take the leftmost (it will be a few microseconds slower, due to
doing MEMBER of a one-element list instead of EQ, not enough slowdown
to matter). I like taking the leftmost better than signalling an error.
(defclass ship ()
((x :initarg :x)
(y :initarg :y)))
(defmethod initialize-instance :after ((s ship) &key startp)
(when startp (start s)))
(defmethod start ((s ship))
(with-slots ((s :use-accesors nil))
(if (AND X Y)
<start it up>
(error "Have to set X and Y before starting a ship."))))
(One line of the above has been uppercased, the only ASCII way to
highlight it.)
I hope this is an erroneous example, and you're not really proposing that
otherwise-uninitialized slots should be initialized to NIL.
the only serious problem has to do with arranging for the default
initarg value forms to be evaluated in the lexical environment of the
defclass. (Of course if environments were first class objects this would
be trivial...)
I thought we agreed that defclass would translate the initforms into
functions and at the metaclass level they would appear as functions. I
don't think we need a new way, besides lambda, for capturing lexical
environments. (Of course implementations are not required to make new
functions in all cases; especially in the case of constant initforms,
they will probably make a closure of an existing function.) This implies
that one cannot use metaclass protocol to recover the original forms
that appeared in the defclass. Maybe we didn't agree on this, I couldn't
find anything about it in my notes from the meeting. Can we converge
on this now?
∂27-Jul-87 2012 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 20:12:22 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 200153; Mon 27-Jul-87 22:46:48 EDT
Date: Mon, 27 Jul 87 22:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July. The rest of this
message is it.
This page is things that I think we agreed that we had decided
after the March meeting and before the July meeting.
27 May 87 call-next-method is allowed to take arguments, however it is
an error to give it arguments that would change the set of applicable
methods. I think we're saying this signals an error, and mentioning
that in some simple cases the lack of need for an error check can be
proved at compile time, but in general a run-time check is required.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
!
This page is a list of issues on which we should make decisions,
brought up by Danny. Where I saw responsive answers in the mail
(there were very few) I have edited them in. I've removed comments
that were purely editorial comments on the document.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, I think
because existing interfaces might not be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this.
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
In July we decided to defer this.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function.
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
We need to decide whether class-name of an anonymous class is nil.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
Kempf agrees they should return the object. Moon isn't sure, because
defun, defvar, deftype, and defstruct return the name. As far as I can
tell every defxxx form in CLtL returns the name. The problem is that
we haven't admitted that defmethod has a name.
In July we decided (for the previous three) to return the object for
all CLOS defxxx functions (being inconsistent with Common Lisp).
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. Then we said we'd discuss it further in the mail.
I think we agreed that the turning of two setf argument lists into one should
depend only on the argument lists, and not on the generic function object.
[My notes include an illegible comment, I think it means that I still hope
we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one.]
p2-39 Arguments: "list of t's" should be replaced by "list of classes
named t" since get-method only takes specializers, not names of
specializers.
Agreed.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
p2-51 print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
Gregor will propose the details.
!
This page is a list I made in March, keyed by page numbers in the
document, that hasn't been shown to anyone yet. Issues mentioned
earlier, or that have since died, have been removed. I've removed
comments that were purely editorial comments on the document.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means.
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
2-13 class-named needs a new name for consistency. get-class would be wrong
because the other get-xxx functions aren't name operations. symbol-class
is the agreed name. It needs an environment argument. The errorp argument
gets in the way. I think we agree that symbol-class should be setf'able,
but can it only be set once for a given symbol or is it allowed to change
the symbol-to-class-object mapping?
2-16 (slot-name form) should be allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
but it never finds its way into the document.
In July we rejected this. Since people keep assuming it, we have
to document explicitly that it is not allowed.
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-40 get-setf-generic-function needs an errorp, but it and ensure-generic-function
should be subsumed by get-generic-function which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Gregor promised to mail out the proposal.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
!
Documented holes in chapters 1 and 2 of 87-002. We publicly promised
X3J13 that we would finish these and have a new draft of 87-003 by the
next meeting.
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
!
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Ida: make-specializable seems to be missing
Gregor's proposal for get-generic-function will subsume this.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
Should we just flush multiple-value-prog2, as leading to more discussion
than is warranted by its simplification of the presentation of
define-method-combination?
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
Should we flush defmethod-setf and friends in favor of function specs?
It probably turns out they could be just in the macros and not in the
underlying Lisp. The big issue is standardizing where the "new-value"
argument goes; but we may do that anyway (mentioned earlier in this file).
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe?
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
The fact that symbol-function (the user callable primitive) needs to
be split from the subprimitive for implementators that gets and sets
the "real" function definition of a symbol. This is so when a symbol's
function definition is a generic function object, the "real" definition
can be something that is easier for the implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gergor volunteered to send some mail about this.
Clarify that because class names and classes are type-specifiers, they can be
validly be used in THE special forms and in TYPE declarations. We forgot this
when we clarified that class objects can be used with TYPEP and SUBTYPEP.
July: agreed
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
Need to be able to get at the obsolete classes associated with a class,
to put methods on them.
Patrick has proposed.
Need discussion of how instances are transformed one step at a time
when a class has been redefined multiple times.
∂28-Jul-87 1447 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 14:46:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 14:46:54 PDT
Date: 28 Jul 87 14:46 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 24 Jul 87
14:59 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-144654-2241@Xerox>
Here is a generic function ``in CLOS'':
Add-method generic-function method
And here is how we have ``carefully laid out ... the range of
legal arguments'' to it:
Arguments:
The generic-function argument is a generic function object.
The method argument is a method object. The lambda-list of
the method function must be congruent with the lambda-lists of any
other methods associated with the generic function and with the
lambda-list of the generic function.
(page 2-5, FUNCTIONS)
We should have been more careful about our wording perhaps. Because we
have not yet formalized the notion of protocol, we have had to say the
the first argument is a generic-function. But it could of course be any
object that satisfied the same protocol (could act as the argument to
some set of generic-functions). It is the ability to specialize (make
"is a generic-function object" mean "be an instance of a subclass of
generic-function object") and the ability to create alternative
implementations that is one of the important improvements that object
oriented programming adds to Lisp -- Hence a MAJOR feature. Users who
ask "what's that thing?" have not understood object oriented
programming, and it is up to us to help explain it -- not apologize for
it.
∂28-Jul-87 1527 Bobrow.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 15:26:54 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 15:26:43 PDT
Date: 28 Jul 87 15:26 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Redefinition
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jul 87
12:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-152643-2322@Xerox>
rpg says
It would be nice if different classes weren't EQ. Is there no
way to make this work?
The problem is what is a different class. People build networks of
objects, including classes. The point of the spec is that these
networks (including the one in the class lattice) should have to change
when a class is changed. People do not always refer to classes by
names.
Response to Moon:
Although I have not thought about it a lot, I think Moon's refinements
GET-CLASS-FOR-NEXT-REDEFINITION
and
GET-OBSOLETE-CLASSES
seems fine. I don't understand the experience of why one gets into
trouble making CLASS-CHANGED methods after redefinition as Moon says,
but perhaps it is because I am not working in a true multi-process
system.
I think we have only two choices with respect to methods applicable to
obsolete instances--
1) All methods applicable to the class itself i.e. the obsolete-class is
a subclass of the new class
2) Only slot-value-using class.
A problem with the first is what happens if a method is removed from a
class before an obsolete instance is converted to a real instance. For
example, in the famous rho-theta example, suppose we have x-y points
(ones with x and y as slots), and decide to change class to store only
rho and theta. Then after redefining the class, a naive user might
1) build a class-changed method that used the methods for rho and theta
for conversion
2) believe that these rho and theta methods could be removed from the
rho-theta-point class.
In this description I have made it obvious why this is wrong. But
suppose this were a case where both of generic functions for rho and
theta used another routine that was no longer needed. The user might
easily delete that one.
I think that it might be better to go to 2, though clearly it makes
class-changed have a lot less easily accessible power.
∂28-Jul-87 1550 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 28 Jul 87 15:49:56 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa18740; 28 Jul 87 18:40 EDT
Received: from ti-csl by RELAY.CS.NET id aa01279; 28 Jul 87 18:30 EDT
Received: from Jenner by tilde id AA20926; Tue, 28 Jul 87 15:53:07 CDT
Message-Id: <2763492729-5527834@Jenner>
Date: Tue, 28 Jul 87 15:52:09 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of Sat, 25 Jul 87 01:26 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
I don't like Patrick's particular proposal, though.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is too complicated, because it
returns a whole alist rather than being just the primitive. In addition, I
don't think the set of "classes implicated in the class-redefinition of
CLASS" is computable until the details of the redefinition are known.
Suppose
(defclass one () (a b))
(defclass two (one) (c))
(defclass three (one) (d))
Now suppose we redefine one as follows:
(defclass one () (a b d))
Referring to the third paragraph on page 1-11 of 87-002, one and two are
"implicated", but three is not, or at least, whether three is implicated is
implementation-dependent. But if the new slot had been named e, both two
and three would have been implicated. I don't think the information in
Patrick's alist is needed anyway; when defining a method, one only defines
it for the obsolete class corresponding to one class. If a different
method needs to be defined for an obsolete subclass, the function can be
called again.
I see. I don't care that much about the alist as long as we can get the
obsolete class of "one".
Thus I would replace Patrick's proposal with GET-OBSOLETE-CLASS-FOR-REDEFINITION
which takes one argument, a class, and returns one value, the obsolete class
that is a copy of the current definition of the class and will be used the next
time the class is redefined; this is created the first time you ask for it.
Perhaps GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION would be a better name.
As Danny proposed, a primitive to get the obsolete classes corresponding to
redefinitions that have already taken place is useful, for instance in case
you didn't realize ahead of time that you would need a CLASS-CHANGED method
and now want to patch up the program. I would suggest a function
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS which takes one argument, a
class, and returns one value, a list of obsolete classes, newest first.
Sounds OK.
I'll have to think some more about the rest of the message. Our
connection with Arpanet was broken and we got it back just one
hour ago.
Patrick.
∂28-Jul-87 1642 Gregor.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 16:42:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 16:42:34 PDT
Date: 28 Jul 87 16:42 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Class Redefinition
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 28 Jul 87 15:26 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-164234-1120@Xerox>
The need for get-class-for-next-redefinition doesn't really have
anything to do with multi-processing as far as I can see. Suppose that
(the class of) one of the objects actually involved in defining a method
on class-changed was going to be rendered obsolete by a certain defclass
form. In that case, you would need to define the method before you
actually change the class definition.
∂28-Jul-87 1648 Gregor.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 16:48:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 16:48:45 PDT
Date: 28 Jul 87 16:48 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Class Redefinition
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 28 Jul 87 15:26 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-164845-1137@Xerox>
As far as "it would be nice if different classes weren't EQ" goes.
Stop thinking about names and naming! If you do, I think it becomes
easier to see why the obsolete class should be a new object and the old
class object should be updated to have the new definition.
defclass just associates a class with a name for convenience. Many
programs will use anonymous classes. In these programs, changes in an
anymous or a named class might cause anymous or named classes to become
obsolete. The obsolete class mechanism needs to support both anonymous
and named classes. In order to do that, the 'redirection' needs to be
at the level of the class object not at the level of the class name.
∂28-Jul-87 1751 Bobrow.pa@Xerox.COM Re: initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 17:51:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 17:51:21 PDT
Date: 28 Jul 87 17:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: initialization meeting notes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 22:05 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870728-175121-1220@Xerox>
This implies that one cannot use metaclass protocol to recover
the original forms that appeared in the defclass.
This seems an unecssary mistake (we could have redundant information at
the very least). I agree that we need not have any "new way, besides
lambda, for capturing lexical
environments."
∂28-Jul-87 1907 Gregor.pa@Xerox.COM Re: initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 19:07:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 19:04:56 PDT
Date: 28 Jul 87 19:04 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: initialization meeting notes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 22:05 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870728-190456-1292@Xerox>
From: Moon
(One line of the above has been uppercased, the only ASCII way
to highlight it.)
I hope this is an erroneous example, and you're not really
proposing that otherwise-uninitialized slots should be initialized
to NIL.
Yes, this example is erroneous. What I was trying to capture was that
an :after initialize-instance method would be able to tell if a slot had
been set.
I thought we agreed that defclass would translate the initforms
into functions and at the metaclass level they would appear as
functions. I don't think we need a new way, besides lambda, for
capturing lexical environments. (Of course implementations are not
required to make new functions in all cases; especially in the case
of constant initforms, they will probably make a closure of an
existing function.) This implies that one cannot use metaclass
protocol to recover the original forms that appeared in the
defclass. Maybe we didn't agree on this, I couldn't find anything
about it in my notes from the meeting. Can we converge on this now?
I remember now that we had agreed that both initforms and default
initargs would be translated into functions by defclass. Note that this
does not necessarily mean that its impossible to reconstruct the
defclass form for a class. We could say that at the metaclass level,
there is a separate mechanism for communicating the form that was in the
defclass.
But I would just as soon agree that there is no such mechanism at the
metaclass level. Actually, I think the fact that Common Lisp doesn't
have first class lexical environments means that its impossible to
construct an 'equivalent' defclass form which an editor might put up for
the user to edit a little and then re-evaluate. Only specific
implementations, in an implementation specific way will be able to do
this.
On the other hand, if Common Lisp had first class lexical environments,
this would be easy. An unemployment would be lower. And the national
debt would be under control, and glphh... uh...
∂28-Jul-87 1922 Gregor.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 19:22:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 19:21:57 PDT
Date: 28 Jul 87 19:21 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Name That Class
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jul 87
11:59 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-192157-1316@Xerox>
It seems to me that there are ways for class-named and setf of such to
work. I think only two of these are reasonable, but I will include the
third for completeness. Note that this same analysis applies to
generic-function-name and setf of symbol-function and
get-setf-generic-function. I will do class names first.
A class C 'is bound to' a given name Ni iff (class-named Ni) returns C.
In all this solutions, we document class-named and setf of class-named.
We say that class-named returns the class is bound to a particular name.
We say that setf of class-named can be used to set the binding of a
class to a name.
Solution 1:
Only document class-named and setf of class-named. Most
implementations will have some magic for printing out a class's name
when it has one.
Solution 2:
Document class-named and setf of class-named. Also document
class-name, but say that the the class may or may not 'bound' to that
name.
Solution 3:
Document class-named and class-names and setf of class-named. Say
that setf of class-named can be used to bind a clas to a name. Say that
class-names returns the list of all names that a class is bound to. For
example:
(setq foo (make-instance 'standard-class))
#<Standard-Class NIL 1>
(setf (class-named 'n1) foo)
#<Standard-Class N1 1>
(setf (class-named 'n2) foo)
#<Standard-Class N2 1>
(class-names foo)
(N1 N2)
(setf (class-named 'n1) nil)
#<Standard-Class N2 1>
(setf (class-named 'n2) nil)
#<Standard-Class NIL 1>
(class-names foo)
()
It seems to me that solution 1 and solution 3 are the only reasonable
ones. My general dislike of names makes me prefer solution 1, but I
think that solution 3 actually provides users some important
functionality.
I think its easy to see how this whole thing would work for
generic-function-name, symbol-function, setf of symbol-function,
get-setf-generic-function and setf of get-setf-generic-function.
∂28-Jul-87 2126 RPG Partial Orderings
To: common-lisp-object-system@SAIL.STANFORD.EDU
You can define a partial ordering based on irreflexive relations
by using the `antirelation' and NOT. For example, instead of less than
or equal, you can use greater than and NOT. If you don't believe me,
believe Knuth Volume 1.
-rpg-
∂29-Jul-87 1025 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Miscellaneous decisions taken or to be taken
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Jul 87 10:25:11 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ac27103; 29 Jul 87 13:10 EDT
Received: from ti-csl by RELAY.CS.NET id af06356; 29 Jul 87 13:02 EDT
Received: from Jenner by tilde id AA12158; Wed, 29 Jul 87 11:22:06 CDT
Message-Id: <2763562862-9741514@Jenner>
Date: Wed, 29 Jul 87 11:21:02 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Msg of Mon, 27 Jul 87 22:46 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
I agree with it.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, I think
because existing interfaces might not be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this.
I agree with Gregor.
∂29-Jul-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM updated documentation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jul 87 10:34:40 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 201218; Wed 29-Jul-87 13:27:29 EDT
Date: Wed, 29 Jul 87 13:26 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: updated documentation
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870729132641.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
I wrote new versions of the functions, concepts, and design chapters.
The documentation now includes the write-up about Standard Type Classes
which I sent to this list several months ago. I didn't receive any
comments about it, probably because the text was cluttered up with tex
formatting directives. When we format the document again it will be
easier for people to read this section and make their comments then.
I changed the documentation to state that the def-XXX macros return
objects, not names. We agreed on this change at our Cambridge meeting
a couple weeks ago.
The only problem with this is some awkwardness about the value of
define-method-combination. There is no CLOS object for representing a
method combination type. define-method-combination expands into a
defmethod, so its result is a method object.
∂29-Jul-87 1415 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Jul 87 14:15:18 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae29814; 29 Jul 87 17:07 EDT
Received: from ti-csl by RELAY.CS.NET id ae07913; 29 Jul 87 17:02 EDT
Received: from dsg by tilde id AA02476; Wed, 29 Jul 87 15:11:11 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Wed, 29 Jul 87 15:00:19 CDT
Message-Id: <2763575892-10524347@Jenner>
Date: Wed, 29 Jul 87 14:58:12 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Class redefinition and class-changed.
In-Reply-To: Msg of Sat, 25 Jul 87 01:26 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
We have our choice of three ways to define what happens when a class is
redefined:
(1) A new class object is created, the name-to-class-object mapping is
changed, defclass-defined methods implied by the new definition are put on
the new class object, all methods other than defclass-defined methods that
apply to the old class are made to apply also to the new class, subclasses
of the old class are made to be subclasses of the new class instead, and
superclasses of the old class are made to be also superclasses of the new
class. If we had done this, there would have been an explicit
representation of versions of a class, and there would not have been any
concept of "obsolete classes."
I don't like this one for the reasons Gregor and Danny gave.
This means that -both- arguments to CLASS-CHANGED could be instances of
obsolete classes. It also means that our CLASS-CHANGED method can't
specialize its second parameter, because at first that will be the class
FOO, but after FOO is redefined again, it will be an obsolete class. If we
don't specialize the second parameter, it seems we could be confused by
CLASS-CHANGED being called when CHANGE-CLASS was used to change an instance
of FOO into an instance of BAR. This is not a problem if CHANGE-CLASS,
like all other generic functions, first updates its argument to the latest
definition of its class, before changing it to the new class; then a method
specialized to an obsolete class in its first parameter can never be called
with the second parameter an instance of anything other than the next newer
version of the same class. This all seems slightly kludgey, but does seem
like it should work.
I like this approach the best because it is more object oriented than
the third one and seems more modular. However it has the problem Danny
mentioned about applicable methods:
[Bobrow]:
I think we have only two choices with respect to methods applicable to
obsolete instances--
1) All methods applicable to the class itself i.e. the obsolete-class is
a subclass of the new class
2) Only slot-value-using class.
A problem with the first is what happens if a method is removed from a
class before an obsolete instance is converted to a real instance. For
example, in the famous rho-theta example, suppose we have x-y points
(ones with x and y as slots), and decide to change class to store only
rho and theta. Then after redefining the class, a naive user might
1) build a class-changed method that used the methods for rho and theta
for conversion
2) believe that these rho and theta methods could be removed from the
rho-theta-point class.
In this description I have made it obvious why this is wrong. But
suppose this were a case where both of generic functions for rho and
theta used another routine that was no longer needed. The user might
easily delete that one.
I think that it might be better to go to 2, though clearly it makes
class-changed have a lot less easily accessible power.
I don't like danny's 1) because as he shows, it does not work. I don't
like 2) because it breaks modularity. You have to know if an accessor
is implemented as a physical slot access and if not, you have to know
what the accessor was doing. This knowledge is contained in your class
and its superclasses.
How about this one?
1b)All methods applicable to the class itself at the time of the
redefinition.
It would be up to the implementation to choose the best way of doing
it.
The third way to define what happens when a class is redefined, mentioned
earlier, is as follows: Don't try to use CLASS-CHANGED for both changing
the class of an instance and updating an instance to a new version of its
class. Invent a new generic function CLASS-REDEFINED, which is called when
an instance is updated to a new version of its class. This avoids the
complicated concept of "obsolete classes", at the cost of conveying the
former state of the instance in a less object-oriented fashion. Perhaps
CLASS-REDEFINED would receive three arguments: an instance of the class,
already updated to the latest definition of the class, a property list
associating slot names to slot values, with one entry for each slot that is
no longer present, and a list of slot names of slots that were newly added
to the instance. Thus when a class is redefined:
(3) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, and the modification is propagated to subclasses. This is simpler
than (1) or (2).
The third way is simpler indeed. My main objection to this is that
CLASS-REDEFINED methods have to know all about the implementation of the
class and superclasses (physical slots and methods) AND the whole story
about the successive redefinitions.
Patrick.
∂30-Jul-87 0021 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Jul 87 00:20:49 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Wed, 29 Jul 87 15:26:18 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Wed, 29 Jul 87 15:24:58 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Wed, 29 Jul 87 16:25:29 pdt
Message-Id: <8707292225.AA09896@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, kempf@hplabsz.hpl.hp.com
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Your message of Mon, 27 Jul 87 22:46:00 -0400.
<870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 29 Jul 87 16:25:25 -0700
From: kempf%hplabsz@hplabs.HP.COM
On anything not noted, I've got no opinion.
There was no mention made of compile time optimization, which I believe
I made some initial proposals on in late April or early May. I've been
meaning to revist them, will try to get to that in the next week or
so. If anybody thinks this isn't important and should be dropped, let
me know. Our applications developers are asking for it, however.
On initialization:
> 1-5, 2-44 The initialization protocol for make-instance is not yet
> specified.
I take it there was no agreement at the July meeting to a full specification?
If so, then can someone write up the specification and post it?
PART I:
> 27 May 87 call-next-method is allowed to take arguments, however it is
> an error to give it arguments that would change the set of applicable
> methods. I think we're saying this signals an error, and mentioning
> that in some simple cases the lack of need for an error check can be
> proved at compile time, but in general a run-time check is required.
This is fine. Do we need to further clarify the error based on Dick's
note about error signaling?
> 10 June 87 There was no response when Sonya mailed out a writeup for how
> the standard type classes are organized. Does that mean we agreed on that?
Yes, modulo consideration of Patrick's suggested change in
<2762944528-5369042@Jenner> for purposes of minimizing category errors.
But I assume from the note he posted today, that he is satisfied with
Sonya's note.
> p1-12 Should defclass be allowed to change the metaclass of an existing
> class? Under what conditions should a subclass of standard-class have
> the same properties wrt instance updating as standard class?
> Kempf says you shouldn't be allowed to change the metaclass, I think
> because existing interfaces might not be transformable.
> Gregor says the metaclass protocol includes a predicate function
> that controls this.
The reason was because the representations might differ. Consider a
metaclass where the types of the slots were restricted. Instances of
classes of a metaclass which did not have those restrictions might be
difficult to update automatically. However, I think Gregor's solution of
a metaclass protocol predicate (generic) function to control this would
be sufficient.
This doesn't answer the second question, however, I'll abstain on that
one. I don't believe instance updating belongs in the language in the
first place, but rather in the environment.
PART II:
> p1-17 "It is currently under discussion whether to provide constructs
> for giving generic functions local names." Do we want to have this
> discussion, or to punt on this syntax. I recall we did come up with some
> reasonble semantics for a GFLET and GFLABELS.
>
> In July we decided to defer this.
Let's forget it for now. I've got some ideas, but I won't rehash them.
> p1-18 It is not specified whether get-setf-generic-function is a
> setf-able form. I suggest that it be made so. This would allow one to
> trace setf-generic-function's without having to know their names.
> This set off a discussion of how TRACE should work that maybe doesn't
> bear directly on CLOS.
> Moon thinks this would be okay provided it is understood as setting the
> mapping from a name to a generic function, not side-effecting the
> generic function.
I've been thinking about modifications to TRACE to support tracing of
generic functions, which combines aspects of Danny's idea of making
TRACE a generic function and Moon's function specs. I'll try to get
it written up and posted by the end of the week. I think it's important
that this be addressed, since our applications developers are beginning
to express the need for the ability to trace individual methods, as
well as invocation of the generic function.
> p1-24 Should we have a call-next-method? which calls such a next method
> if it exists, else returns nil (rather than signalling an error?). This
> seems useful rather than having to define many base methods on object.
CommonObjects had two messaging forms for this, but my general inclination
is to conform with what happens when an attempt to invoke a generic
function is made with an argument set for which there is no matching
method. Currently, an error is signalled, and I think that it should
also be for CALL-NEXT-METHOD.
> We need to decide whether class-name of an anonymous class is nil.
Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
second. An anonymous class should be a class with NO name.
> p2-19 Values: I thought we agreed that all top level forms should return
> the object. It says here defclass "returns the name of the class"
> p2-22 Same comment as 2-19, for defgeneric-options
> 2-24 ditto for defgeneric-options-setf
> Kempf agrees they should return the object. Moon isn't sure, because
> defun, defvar, deftype, and defstruct return the name. As far as I can
> tell every defxxx form in CLtL returns the name. The problem is that
> we haven't admitted that defmethod has a name.
> In July we decided (for the previous three) to return the object for
> all CLOS defxxx functions (being inconsistent with Common Lisp).
Additionally, it would be nice if
top level forms would also print out something at compile time. Our
applications developers are asking for some feedback about what gets
done at compile time. Maybe that's an implementation issue, though.
> p2-35 The argument order of the setf method ought to be documented here.
> Gregor proposed that new-value be the first argument. Any problem with
> this?
> Kempf doesn't care but his users want it to be the second argument.
> Moon doesn't care but his users are used to it being the last argument.
> In July we suggested making the new-value argument a required argument that
> comes after all the other required arguments, and before the optional, rest
> and keyword arguments. Then we said we'd discuss it further in the mail.
> I think we agreed that the turning of two setf argument lists into one
> should
> depend only on the argument lists, and not on the gen eric function object.
> [My notes include an illegible comment, I think it means that I still hope
> we can keep things abstract enough that we don't have to document
> how the two setf argument lists are turned into one.]
This sounds good to me.
> p2-39 Arguments: "list of t's" should be replaced by "list of classes
> named t" since get-method only takes specializers, not names of
> specializers.
Yes, except I'd phrase it as "a list whose elements are the class object
for the the class named T". As I understand it, there is only one class T.
> p2-51 print-object should take a depth argument.
> Moon strongly disagrees and points to the fourth bullet. I believe this
> issue was discussed to death on the Common Lisp mailing list a few months
> or a year ago.
> The point is that every single method for print-object should not have to
> deal with *print-level*; that's unmodular.
> Kempf raised a consistency argument (with defstruct?) but we decided
> not to change print-object.
I agree with Moon. Some implementors may scream (as I did),
but it's probably not too late to correct this blemish.
PART III:
> 2-6 call-next-method dynamic versus indefinite extent
> The document says it has dynamic extent; we need to be sure that we
> really mean that. In July we said "implementation flexibility, not
> really a language thing", but I'm damned if I can figure out what
> that means.
Yes, this needs to be resolved. See my comments below about adding
methods to more than one generic function. Although I wasn't there,
I think the "implementation flexibility" comment had something to
do with optimizing calculation of the effective method. Indefinite
extent would favor this, but dynamic extent would give more flexibility
with regard to what could be done with method objects. Indefinite
extent sounds good to me, but I'm not particularly choosy, however,
I think it should be pinned down.
> 2-9 semantic difficulties discussion was shortened for the document so much
> that much of the point was lost. At some point we need to decide how much
> we want to standardize about this and where we want to say it; in the main
> standard or in some kind of implementation guide.
I think these semantic difficulties point out a fundamental problem with
CHANGE-CLASS. It is neither a full versioned class capability nor an
environmental undo capability, but rather a hack somewhere in between. Having
said my peace (and above, about instance changing), I'll forgoe any
further comments.
> 2-13 class-named needs a new name for consistency. get-class would be wrong
> because the other get-xxx functions aren't name operations. symbol-class
> is the agreed name. It needs an environment argument. The errorp argument
> gets in the way. I think we agree that symbol-class should be setf'able,
> but can it only be set once for a given symbol or is it allowed to change
> the symbol-to-class-object mapping?
Why an environment argument? Since we haven't agreed to lexically scoped
class names, this would seem unnecessary. Is it to deal with the ERRORP
argument? Why do people think it will get in the way? Why not just make
it a keyword argument? A user might want to not have it signal an error
especially in metaclass programming. If whether or not it signals an
error is dependent on a (second-class) environment argument, then it
will be more difficult for a user to arrange. I think the name SYMBOL-CLASS
is OK, and that it should be allowed to change the
symbol-to-class-object mapping.
The important thing in CLOS is the object, and the name to object mapping
should be changable.
> 2-16 (slot-name form) should be allowed as an abbreviation
> for (slot-name :initform form). People have been assuming this,
> but it never finds its way into the document.
> In July we rejected this. Since people keep assuming it, we have
> to document explicitly that it is not allowed.
Yes.
> 2-16 boa-arglist should support &key and &allow-other-keys.
Agreed.
> 2-19 uninitialized slots should be an error to reference, not be defined
> to return an unstandardized value with no error. I'm willing not to require
> that it signals an error if people feel that would be an undue burden,
> otherwise I prefer that reading an uninitialized slot signals an error.
I agree that it should signal an error.
> In July we decided that signalling an error here should depend on the
> declared safety level. Dick has proposed terminology for this.
Dick's terminology is good. We probably need to backpatch it into the
document (it should probably be backpatched into CLtL too, but that's
not for us to decide).
> 2-57 with-slots :prefix package problem; This was discussed in the mail and
> then the ball was dropped. What's in the document is unworkable because it
> depends on the dynamic value of *package* at macro-expansion time, but Common
> Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
> prefer to flush the :prefix option. An alternative
> that was discussed was to
> use symbol-package of the prefix, both here and in defclass accessor construc-
tion,
> as the package, relying on the likelyhood of prefixes always ending in delimi-
ter
> characters and exported symbols never ending in delimiter characters.
> July: We agreed to resolve this in the mail.
I agree with Moon.
> 2-57 What does with-slots do for slots that exist in the class but don't
> have accessors, when :use-accessors t is specified (or defaulted)?
> July: it shadows any outer bindings of the slot name, and if you
> actually access that pseudo-variable, it signals an error.
Agreed.
> Documented holes in chapters 1 and 2 of 87-002. We publicly promised
> X3J13 that we would finish these and have a new draft of 87-003 by the
> next meeting.
See my note of 27 July to Dick about holes in Chapter 1. I'll be replying
to Danny's comments on it shortly.
> 1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
> is still under discussion.
Has a Cleanup Committee proposal been submitted for the type system?
> What can be done with method objects, e.g. can one method be added
> to more than one generic function?
There may be a problem if the method invokes CALL-NEXT-METHOD. This
relates back to whether CALL-NEXT-METHOD is dynamic or indefinite
in extent. If it is dynamic, then there should be no problem, since
the binding of CALL-NEXT-METHOD is done when the method begins executing,
at the latest, or during calculation of the effective method, at the
earliest. Thus the same method object on multiple generic functions
would be no problem, since that case could be detected and establishment
of CALL-NEXT-METHOD's binding deferred as late as possible. If the
extent is indefinite, then the binding could potentially remain outside
of a particular method invocation, and so adding the same method to
more than one generic function may cause a problem.
> Ida: make-specializable seems to be missing
> Gregor's proposal for get-generic-function will subsume this.
Wasn't ENSURE-GENERIC-FUNCTION supposed to replace this?
> Should we just flush multiple-value-prog2, as leading to more discussion
> than is warranted by its simplification of the presentation of
> define-method-combination?
Yes.
> Which symbols defined by the standard go in what package?
> July: I think we said some will go in LISP: and some will go in CLOS: and
> we don't know yet where to draw the line.
I think they should all go into CLOS, except those which are already in
LISP (like DOCUMENTATION) or those which are designed to replace aspects
of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
> Should we flush defmethod-setf and friends in favor of function specs?
> It probably turns out they could be just in the macros and not in the
> underlying Lisp. The big issue is standardizing where the "new-value"
> argument goes; but we may do that anyway (mentioned earlier in this file).
I think we ought to keep DEFMETHOD-SETF, but use function specs (or
something like them) as the programmer interface to TRACE. See my
comments above about TRACE.
> Should we adopt the :component-order class-option from Flavors, as a
> simple way for the user to have control of the CPL without making him
> write his own algorithm?
> Gregor doesn't like the ability to specify constraints on the ordering
> of classes that only apply conditionally, i.e. if those classes are
> actually present among the superclasses. He considers this bad style.
> Moon volunteered to write a proposal with some examples, and we agreed
> to resolve this over the mail.
I agree with Gregor. I think that user specified changes in the CPL
should be controlled through COMPUTE-CLASS-PRECEDENCE-LIST, or, if
the default algorithm can't make a decision.
> The fact that symbol-function (the user callable primitive) needs to
> be split from the subprimitive for implementators that gets and sets
> the "real" function definition of a symbol. This is so when a symbol's
> function definition is a generic function object, the "real" definition
> can be something that is easier for the implementation to call.
I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations. Currently, most of the
PCL-derived implementations have no trouble with this.
> July: We need to say explicitly somewhere that calling symbol-function
> of the name of a generic function is required to return the generic
> function object, not the "real" definition.
Yes.
> I'm not sure if we said anywhere what happens when you call a generic
> function and there is no applicable method; I think it ought to signal
> an error.
Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
in the context of Dick's proposed error naming scheme.
> Clarify that because class names and classes are type-specifiers, they can be
> validly be used in THE special forms and in TYPE declarations. We forgot this
> when we clarified that class objects can be used with TYPEP and SUBTYPEP.
> July: agreed
Yes. Again, as mentioned in the beginning, this relates back to compile
time optimization.
> funcallable-standard-class should be documented. It is a metaclass.
> This is what makes generic function objects funcallable. There is a slot
> that is the actual function that gets called.
Agreed.
∂30-Jul-87 0612 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Miscellaneous decisions taken or to be taken
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 30 Jul 87 06:12:35 PDT
Received: from [128.89.1.80] by RELAY.CS.NET id aa02415; 30 Jul 87 9:08 EDT
Received: from ti-csl by RELAY.CS.NET id ad12225; 30 Jul 87 9:02 EDT
Received: from Jenner by tilde id AA02135; Thu, 30 Jul 87 07:59:04 CDT
Message-Id: <2763637077-14200445@Jenner>
Date: Thu, 30 Jul 87 07:57:57 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Msg of Wed, 29 Jul 87 16:25:25 -0700 from kempf%hplabsz@hplabs.hp.com
> We need to decide whether class-name of an anonymous class is nil.
Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
second. An anonymous class should be a class with NO name.
If we signal an error on class-name, then we have to come up with a
predicate to test if the class is named or not. Is it worth the trouble?
Additionally, it would be nice if
top level forms would also print out something at compile time. Our
applications developers are asking for some feedback about what gets
done at compile time. Maybe that's an implementation issue, though.
You're right, it is an implementation issue, some compilers have a
verbose option.
> 2-13 class-named needs a new name for consistency. get-class would be wrong
> because the other get-xxx functions aren't name operations. symbol-class
> is the agreed name. It needs an environment argument. The errorp argument
> gets in the way. I think we agree that symbol-class should be setf'able,
> but can it only be set once for a given symbol or is it allowed to change
> the symbol-to-class-object mapping?
Why an environment argument? Since we haven't agreed to lexically scoped
class names, this would seem unnecessary. Is it to deal with the ERRORP
argument? Why do people think it will get in the way? Why not just make
it a keyword argument? A user might want to not have it signal an error
especially in metaclass programming. If whether or not it signals an
error is dependent on a (second-class) environment argument, then it
will be more difficult for a user to arrange. I think the name SYMBOL-CLASS
is OK, and that it should be allowed to change the
symbol-to-class-object mapping.
The important thing in CLOS is the object, and the name to object mapping
should be changable.
The environment argument will be necessary to address the compile
environment problem. The term might be confusing, it is not necessary
an environment like the &environment argument in a macro definition.
> What can be done with method objects, e.g. can one method be added
> to more than one generic function?
There may be a problem if the method invokes CALL-NEXT-METHOD. This
relates back to whether CALL-NEXT-METHOD is dynamic or indefinite
in extent. If it is dynamic, then there should be no problem, since
the binding of CALL-NEXT-METHOD is done when the method begins executing,
at the latest, or during calculation of the effective method, at the
earliest. Thus the same method object on multiple generic functions
would be no problem, since that case could be detected and establishment
of CALL-NEXT-METHOD's binding deferred as late as possible. If the
extent is indefinite, then the binding could potentially remain outside
of a particular method invocation, and so adding the same method to
more than one generic function may cause a problem.
> Which symbols defined by the standard go in what package?
> July: I think we said some will go in LISP: and some will go in CLOS: and
> we don't know yet where to draw the line.
I think they should all go into CLOS, except those which are already in
LISP (like DOCUMENTATION) or those which are designed to replace aspects
of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
We said that some of the symbols will go to LISP because CLOS is
supposed to be part of ANSI Common Lisp. The top level macros and
functions should be part of LISP. The internal functions specified for
the sake of metaclass programming can reside in CLOS.
> Gregor doesn't like the ability to specify constraints on the ordering
> of classes that only apply conditionally, i.e. if those classes are
> actually present among the superclasses. He considers this bad style.
> Moon volunteered to write a proposal with some examples, and we agreed
> to resolve this over the mail.
I agree with Gregor. I think that user specified changes in the CPL
should be controlled through COMPUTE-CLASS-PRECEDENCE-LIST, or, if
the default algorithm can't make a decision.
Let's see what Moon's proposal before discussing the issue.
> I'm not sure if we said anywhere what happens when you call a generic
> function and there is no applicable method; I think it ought to signal
> an error.
Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
in the context of Dick's proposed error naming scheme.
If we can assume that the ANSI will standardize an error handler then I
am in favor of signalling an error and specifying the signal name. If
we can't assume that, I would rather call a generic function like
NO-MATCHING-METHOD.
∂30-Jul-87 1306 Bobrow.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Jul 87 13:06:15 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JUL 87 18:36:33 PDT
Date: 29 Jul 87 18:36 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Name That Class
In-reply-to: Gregor.pa's message of 28 Jul 87 19:21 PDT
To: Gregor.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870729-183633-103@Xerox>
I support proposal 3
(setf(class-named <symbol>) <class>)
and
(class-names <class>)
for the reasons given
danny
∂31-Jul-87 0939 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Jul 87 09:38:35 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 30 Jul 87 15:21:28 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 30 Jul 87 15:21:04 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 30 Jul 87 16:21:49 pdt
Message-Id: <8707302221.AA01264@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Your message of Thu, 30 Jul 87 07:57:57 -0500.
<2763637077-14200445@Jenner>
Date: Thu, 30 Jul 87 16:21:46 MST
From: kempf%hplabsz@hplabs.HP.COM
> > We need to decide whether class-name of an anonymous class is nil.
>
> Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
> second. An anonymous class should be a class with NO name.
> If we signal an error on class-name, then we have to come up with a
> predicate to test if the class is named or not. Is it worth the trouble?
This is a problem. Also with unnamed generic function objects, and
methods. In the interest of simplicity, I'd be willing to forgo this.
I can't think of why anyone would want to name a class NIL anyway.
> The environment argument will be necessary to address the compile
> environment problem. The term might be confusing, it is not necessary
> an environment like the &environment argument in a macro definition.
>
We need some more discussion on this first. I agree that the the compile
environment problem needs solution (especially for single address space
implementations) but I'd rather see some concensus on a general solution
before bringing up specific functions. Even if it means having to revise
the parameter lists of some functions.
>
> I think they should all go into CLOS, except those which are already in
> LISP (like DOCUMENTATION) or those which are designed to replace aspects
> of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
>
> We said that some of the symbols will go to LISP because CLOS is
> supposed to be part of ANSI Common Lisp. The top level macros and
> functions should be part of LISP. The internal functions specified for
> the sake of metaclass programming can reside in CLOS.
Does this mean that a decision was made at the July meeting on the point
Pavel Curtis raised at the March meeting about what relationship CLOS
should have with the full language standard? Unless implementors of
Common Lisp are required to implement CLOS in order to have "full
ANSI Standard Common Lisp", I think it would be better to allow some
flexibility in where the symbols go.
> > I'm not sure if we said anywhere what happens when you call a generic
> > function and there is no applicable method; I think it ought to signal
> > an error.
>
> Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
> in the context of Dick's proposed error naming scheme.
> If we can assume that the ANSI will standardize an error handler then I
> am in favor of signalling an error and specifying the signal name. If
> we can't assume that, I would rather call a generic function like
> NO-MATCHING-METHOD.
I agree with your preferences here. The error message should also give some
information about the classes of the parameters, in addition, to help
debugging.
∂31-Jul-87 1110 kempf%hplabsz@hplabs.HP.COM TRACE Proposal (Version 1)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Jul 87 11:09:44 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Fri, 31 Jul 87 11:07:37 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 31 Jul 87 11:07:05 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 31 Jul 87 12:07:43 pdt
Message-Id: <8707311807.AA10361@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: TRACE Proposal (Version 1)
X-Mailer: mh6.5
Date: Fri, 31 Jul 87 12:07:37 MST
From: kempf%hplabsz@hplabs.HP.COM
As promised, here is an initial draft of a proposal for modifying the
TRACE macro (CLtL, pp. 440-441) to better support object-oriented
programming. The proposal is motivated by the expressed need of our
applications programmers. Sometimes, they would like to only trace
when a particular method is run, rather than tracing every method
when the generic function is invoked. Additionally, some constructs
in Common Lisp which are usually implemented as functions (macroexpansions,
SETF's) are currently not tracable through the TRACE function, but rather
require extra effort. There is obviously lots of room for implementation
dependency here, and some things which would be nice to do portably
(like tracing local function invocations) are difficult because Common
Lisp doesn't have the right constructs (like no first class environments).
The proposal is a combination of Moon's function spec idea, at the
programmer interface level, and Danny's generic function idea, at the
system level. I think most Common Lisp implementors probably include
some help for tracing methods already, if they implement an object-oriented
language.
---------------------------------------------------------------------------------
TRACE &REST {function-spec}* [Macro]
Invoking TRACE with one or more function specifications causes the
functions specified to be traced. Henceforth whenever a specified
function is invoked, information about the call, the arguments passed,
and the returned values, if any, will be printed to the stream that is
the value of *TRACE-OUTPUT*.
A function-spec is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a function specification type, and
whose tail indicates which particular function of that type should
be traced. The complete set of function specification types will
necessarily be implementation specific, but all implementations
are required to provide the following:
<symbol>-Invocation of the function named by <symbol> via. <symbol>'s
global function cell are traced.
(:SETF <place> )-If the generalized variable reference indicated by
<place> is tracable, then invocations of the function implementing
the SETF operation will be traced.
(:METHOD <generic-function-name> <parameter-specializer-name-list>)-
If the method whose parameter specializer list and generic function
are indicated in the specification is tracable, then invocations
through the generic function name will be traced.
(:MACRO-FUNCTION <symbol>)-If <symbol> has a global function definition
that is a macro definition, then invocations of the macro function through
<symbol> will be traced.
>>>>others? Some which I can think of that might be useful are:
(:LOCAL <symbol> <environment>)-Invocations of the function named
<symbol> when the current environment is <environment> are traced.
Problems: Environments are second-class in Common Lisp. Something similar
would be:
(:LOCAL <global-function-symbol> <local-function-symbol>)-Same, except
would get at the environment via. a global function name. This won't take
care of FLETS inside FLETS, nor of FLETS at the top level, however.
This could also be potentially handled via. the macro's environment
parameter.
(:FUNDEF <function definition object>)-Invocations of the function
definition object are traced, regardless of whether they are through
a global or local name symbol.
Problems: Wrapping the function to trace invocation may require modifying the
function definition object, which may not be possible in all
implementations of Common Lisp.
Slot initialization functions, and lambdas are other items which need
consideration.
Note: Another useful enhancement would be to support a :BREAK flag, like
this:
(:METHOD <spec> :BREAK)
indicating that a break loop should be entered before and after the
function executes. Most implementations support this, but it is not
in CLtL. This may be an issue for the cleanup committee, however.
<<<<<<<<<<
TRACE-EXECUTION object &OPTIONAL env [Generic Function]
TRACE-EXECUTION discriminates on object to select an implementation
specific method that arranges for the executable entity associated
with object to be traced. The optional env environment parameter is for
those implementations which require environmental information to
arrange for tracing to occur. Implementations are required to provide
TRACE-EXECUTION as the system level entry point for implementing trace
functionality.
The exact nature and number of methods associated with TRACE-EXECUTION
will differ, depending on what function specifications are supported
by TRACE, but every implementation needs to support the following:
SYMBOL-The function indicated by the symbol will be traced when invoked
in the environment. If the function is a macro, then tracing will occur
when the macro function is invoked. If the function definition is bound to
the symbol's global function definition cell, then invocations of
the function via. its global name will be traced. If the function is a
local function, then only invocations when the environment parameter is
the current environment will be traced, provided the implementation can
arrange for it.
METHOD-The method function is traced when invoked.
GENERIC-FUNCTION-The generic function is traced when the discriminator
code is invoked.
FUNCALLABLE-STANDARD-CLASS-???? need more information about what
this is.
>>>>>>>>>others? Some which I can think of are:
FUNCTION-Invocation of the function is traced, regardless
of whether invocation is through a named symbol. This will obviously
depend on whether modifications in fundefs are allowed to support
tracing.
∂02-Aug-87 1725 RPG Miscellenia
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.''
I am willing to write up a proposal for this, basing it on our latest
thoughts from the mail, if people wish. I do not feel strongly about
this at the moment.
Moon writes:
``p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"''
I believe we originally tried to be consistent with all other DEF<mumble>s
in returning a name. I believe we decided it was ok to return an object
in CLOS DEF<mumble>s.
[Note: Hackers are proud of having invented the `mumble' convention. However,
there is rarely anything new under the sun. Here is a quote from the Saturday,
August 25, 1753 Adventurer by Samuel Johnson:
``I remember,'' says he, ``it was on just such a morning as
this that I and my lord Mumble and the Duke of Tenterden were
out upon a ramble....''
``Tenterden'' is someone who tends a den.]
-rpg-
∂03-Aug-87 1656 kempf%hplabsz@hplabs.HP.COM Re: Miscellenia
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 3 Aug 87 16:56:04 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 3 Aug 87 15:32:53 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 3 Aug 87 15:32:17 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 3 Aug 87 16:33:03 pdt
Message-Id: <8708032233.AA06651@hplabsz.hpl.hp.com>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellenia
In-Reply-To: Your message of 02 Aug 87 17:25:00 -0700.
Date: Mon, 03 Aug 87 16:32:57 MST
From: kempf%hplabsz@hplabs.HP.COM
>
> ``p1-17 "It is currently under discussion whether to provide constructs
> for giving generic functions local names." Do we want to have this
> discussion, or to punt on this syntax. I recall we did come up with some
> reasonble semantics for a GFLET and GFLABELS.''
> I am willing to write up a proposal for this, basing it on our latest
> thoughts from the mail, if people wish. I do not feel strongly about
> this at the moment.
I also don't feel strongly about it at the moment, but a proposal would be
good, if other people agree. Originally, there was some talk about a
GFLAMBDA, but that didn't seem to make it into the document. If you're
open for suggestions, a useful primitive that might address all these
uses might be GFUNCTION, similar to the FUNCTION special form, except
it takes multiple lambda's as arguments.
> [Note: Hackers are proud of having invented the `mumble' convention. However,
> there is rarely anything new under the sun. Here is a quote from the Saturday
,
> August 25, 1753 Adventurer by Samuel Johnson:
> ``I remember,'' says he, ``it was on just such a morning as
> this that I and my lord Mumble and the Duke of Tenterden were
> out upon a ramble....''
> ``Tenterden'' is someone who tends a den.]
Interesting. My English friends tend to use "doobrey" as an unbound in
similar circumstances, viz. DEF<doobrey>. Perhaps, in the 200 odd years
since we've been independent, the language has diverged, like the
pronounciation of "clerk".
I used to occasionally use "X" as an unbound, but, thanks to
Bob Schieffler, that's out now.
jak
∂04-Aug-87 2243 kempf%hplabsz@hplabs.HP.COM Re: Technical corrections in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Aug 87 22:43:16 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 4 Aug 87 14:52:14 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 4 Aug 87 14:51:51 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 4 Aug 87 15:52:31 pdt
Message-Id: <8708042152.AA10558@hplabsz.hpl.hp.com>
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, olthoff%hplabsz@hplabs.HP.COM
Subject: Re: Technical corrections in 87-002
X-Mailer: mh6.5
In-Reply-To: Your message of 28 Jul 87 15:02:00 -0700.
<870728-150405-2277@Xerox>
Date: Tue, 04 Aug 87 15:52:27 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry it's taken so long to answer this.
JAK> As a counterexample, consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4
JAK> c6)}
This is, in fact, incorrect, as Danny pointed out. It should be:
R = { (c1,c2),(c2,c3),(c3,c4),(c3,c5),(c4,c6) }
by the algorithm at the top of pg. 1-14. But see below for more.
JAK> The inheritance graph for this is;
JAK> c5 c6
JAK> | |
JAK> c3 c4
JAK> | |
JAK> \ /
JAK> \ /
JAK> c2
JAK> |
JAK> c1
DB> This counterexample is wrong in that the inheritance graph must specify
DB> a local ordering of c3 and c4 (if vertical means direct superclass and
DB> horizontal is an ordered list.
The intention was that the numbers would indicate the local precedence
ordering. Thus the CLOS definitions would look like:
(defclass c6 () ...)
(defclass c5 () ...)
(defclass c4 (c6) ...)
(defclass c3 (c5) ...)
(defclass c2 (c3 c4) ...)
(defclass c1 (c2) ...)
In fact, the counterexample is wrong, but the interesting fact is
WHY. The counterexample was generated by looking at the pie example
on pg. 1-15, where R is given as:
R = { (pie,apple) (pie,cinnamon),(apple,cinnamon),(apple,fruit),
(cinnamon,spice),(fruit,food),(spice,food),(food,t)
}
However, this is incorrect. The correct value of R before the start
of CPL construction is:
R = { (pie,apple),(apple,cinnamon),(apple,fruit),(cinammon,spice),
(fruit,food),(spice,food),(food,t)
}
This follows by merging the R(C) for each of the classes:
R(pie) = { (pie,apple),(apple,cinnamon) }
R(apple) = { (apple,fruit) }
R(cinnamon) = { (cinnamon,spice) }
R(fruit) = { (fruit,food) }
R(spice) = { (spice,food) }
R(food) = { (food,T) }
Thus the entry (pie,cinnamon) in R is incorrect, and leads to a lack
of the local precedence order being reflected in R.
The R in the counterexample was constructed directly from this example.
Perhaps someone has noted this before and corrected it. In any event,
I suspect that some of the confusion expressed by Sherlis and others
at the March meeting may have been a result of trying to understand
the algorithm via the example. We have had several people here run
into that problem.
DB> The partial order relationship that Dick defines is the one using the
DB> relation "is the same or is subclass of" This one is reflexive, though
DB> we don't have a simple name for it.
This relationship should be sufficient, but I think it should be
made explicit on the top of pg. 1-14. We need not have a simple name,
as long as it is defined. Leaving it implict leaves room for confusion.
I hope whoever is the current custodian of 87-002 can make these corrections.
jak
∂05-Aug-87 1751 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Aug 87 17:51:40 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 AUG 87 17:48:48 PDT
Date: 5 Aug 87 17:48 PDT
From: Kelley.pa@Xerox.COM
Subject: Re: ECOOP Reaction to CLOS
In-reply-to: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>'s message of Thu, 9
Jul 87 13:24:38 pdt
To: kempf%hplabsz@hplabs.HP.COM
Cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870805-174848-5665@Xerox>
In dealing with the intractability of the effect of the proposed CLOS
mechanism for multiple inheritance, violation of the "implicit
inheritance - explicit override" rule should be factored out of the
complexity of the linearization algorithm. Each contribute to the
complexity of the CLOS proposal, but hopefully by distinguishing them
and dealing with each seperately, the total complexity can be reduced.
The CLOS proposed standard explicitly claims in general to obey the
implicit inheritance - explicit override rule, but it does not for
multiple inheritance of slots and methods with the same name. Instead,
it actually reverses the rule in this case. Overriding is implicit and
one must explicitly inherit (via qualifiers).
In as much as implicit inheritance is a sub-conscious assumption of
application programmers, standard CLOS behaves in a counter intuitive
manner.
(defclass border (object) (width))
(defmethod close (b border) ...)
(defclass window (object) (width))
(defmethod close (w window) ...)
(defclass bordered-window (border window))
(setq b-window (make-instance 'bordered-window))
(close b-window) ; with the current inheritance algorithm, only closes
the border. Does not close the window.
The following explores what could happen if the implicit inheritance -
explicit override rule were followed in CLOS.
(close b-window) would result in both the border and window close
methods getting called because it inherits them implicitly and has not
explicitly overridden them.
With implicit inheritance a class may have in addition to multiple
methods with the same name that all get called by one call, multiple
occurrences of a slot with the same name that are manipulated in one
operation so b-window would contain two slots named width.
(setf (slot-value b-window width) 0)
Would set both slots to 0.
A problem is what to do with the results of an operation on a slot name
that refers to two or more slots or on a call that refers to two or more
methods. Operating on these slots or methods that have not been
overridden could be specified to return a "multiple-inheritance-result"
object containing the multiple results.
Any code that depended on the results from instances of singly inherited
classes would not work correctly with instances of multiply inherited
classes. (In the example above, any code that depended on the value
returned by the "close" method on an instance of the window class would
not work on an instance of the bordered-window class.) A blatant error
would usually be generated at run time. A warning of potential such
behavior at definition time might be a desireable feature.
All the unqualified inherited methods with the same name would still
have to get executed in some order. However, it would be possible to
simply specify that these operations are executed in a random order.
-- kirk
∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellenia
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 12:48:53 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208062; Thu 6-Aug-87 13:55:31 EDT
Date: Thu, 6 Aug 87 13:55 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellenia
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 2 Aug 87 20:25 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870806135534.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Aug 87 1725 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon writes:
``p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.''
I am willing to write up a proposal for this, basing it on our latest
thoughts from the mail, if people wish. I do not feel strongly about
this at the moment.
Please do write the proposal. But I wouldn't consider this high priority
at the moment, since you don't feel strongly about it and no one else has
said they feel strongly.
∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM TRACE Proposal (Version 1)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 12:49:12 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208071; Thu 6-Aug-87 14:09:57 EDT
Date: Thu, 6 Aug 87 14:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: TRACE Proposal (Version 1)
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU, Masinter.pa@XEROX.COM
In-Reply-To: <8707311807.AA10361@hplabsz.hpl.hp.com>
Message-ID: <870806141000.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Fri, 31 Jul 87 12:07:37 MST
From: kempf%hplabsz@hplabs.HP.COM
As promised, here is an initial draft of a proposal for modifying the
TRACE macro (CLtL, pp. 440-441) to better support object-oriented
programming....
This looks interesting. I have a couple of comments to offer right now.
A function-spec is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a function specification type, and
whose tail indicates which particular function of that type should
be traced.
The Cleanup subcommittee of X3J13 were discussing something similar
a while back, starting from a different point. The DOCUMENTATION function
of Common Lisp introduces the concept of "definition types", and this
concept could be useful in other operations. For instance, it would be
nice to be able to remove any definition (function, variable, type, setf)
through a uniform interface. "Definition type" and "function spec type"
are not the same concept, however there seems to be enough overlap here
that some coordination is probably called for.
I don't remember for sure, but I think Larry Masinter volunteered to make
a proposal for "definition types" when he got time.
....
Note: Another useful enhancement would be to support a :BREAK flag, like
this:
(:METHOD <spec> :BREAK)
indicating that a break loop should be entered before and after the
function executes.
Here you see a conflict between lists as function-specs and lists as
lists of options, in the arguments to TRACE. Because of this your proposal
for TRACE is not compatible with what Symbolics currently does, but I don't
think that's too important for us. We say that a list is a list of options,
and if you want to trace a function whose name is a list, you have to do
(TRACE (:function <function-spec> <options>...)). But all this really
shows is that the syntax of TRACE is ridiculous. I usually ignore the TRACE
function and trace things through a command interface. Anyway, for your
proposal you have to decide between lists as function specs and lists as
options; I don't think you can mix them freely as you proposed. Of course
it would be a lot easier if TRACE only traced one function at a time,
then the rest of the form could be used for options. That would be a bit
incompatible with CLtL.
TRACE-EXECUTION object &OPTIONAL env [Generic Function]
I didn't completely understand this. It looks like there is some
incoherence about whether TRACE is an operation on functions or on
places in which you can store a function definition. In other words,
does tracing a function redefine the function or alter the object that
is the function's definition? In other words, does
(defun foo () ...)
(setq f #'foo)
(trace foo)
(funcall f)
generate trace-output or not? We have to decide one way or the other.
CLtL is obscure on this point.
∂06-Aug-87 1914 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Name That Class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 19:14:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208497; Thu 6-Aug-87 22:14:54 EDT
Date: Thu, 6 Aug 87 22:14 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870728-192157-1316@Xerox>
Message-ID: <870806221457.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Jul 87 19:21 PDT
From: Gregor.pa@Xerox.COM
It seems to me that there are ways for class-named and setf of such to
work. I think only two of these are reasonable, but I will include the
third for completeness. Note that this same analysis applies to
generic-function-name and setf of symbol-function and
get-setf-generic-function. I will do class names first.
A class C 'is bound to' a given name Ni iff (class-named Ni) returns C.
In all this solutions, we document class-named and setf of class-named.
We say that class-named returns the class is bound to a particular name.
We say that setf of class-named can be used to set the binding of a
class to a name.
All agreed, except I think we decided a month ago to rename class-named to
symbol-class, to be more consistent with the rest of Common-Lisp.
Solution 1:
Only document class-named and setf of class-named. Most
implementations will have some magic for printing out a class's name
when it has one.
Solution 2:
Document class-named and setf of class-named. Also document
class-name, but say that the the class may or may not 'bound' to that
name.
Solution 3:
Document class-named and class-names and setf of class-named. Say
that setf of class-named can be used to bind a clas to a name. Say that
class-names returns the list of all names that a class is bound to.
It seems to me that solution 1 and solution 3 are the only reasonable
ones. My general dislike of names makes me prefer solution 1, but I
think that solution 3 actually provides users some important
functionality.
That's interesting, because I prefer solution 2, for the simple reason
that everything else I can think of that has a name works that way. The
symbol->object mapping is the "real" one, and the object->symbol mapping
is only a helpful hint for printing things out, but isn't necessarily kept
consistent with the symbol->object (a programming environment might try
to keep it consistent).
As far as I am concerned, any of these three would work. My objection
to solution 3 is primarily that it is more complicated. My objection to
solution 1 is that it is the same as solution 2 as soon as the users
discover what the name of the class-name function is, and no useful
purpose is served by making this name implementation-dependent.
....
(setf (class-named 'n1) nil)
#<Standard-Class N2 1>
Is this really how we want to undo these bindings? Nothing else in Common
Lisp I can think of works this way (storing nil). Also, a minor nit, CL
requires that such a setf form return nil, not the former value.
I think its easy to see how this whole thing would work for
generic-function-name, symbol-function, setf of symbol-function,
get-setf-generic-function and setf of get-setf-generic-function.
Agreed. Note that (setf (symbol-function 'foo) nil) isn't how we do
(fmakunbound 'foo) in CL currently.
∂06-Aug-87 1929 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 19:29:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208512; Thu 6-Aug-87 22:29:57 EDT
Date: Thu, 6 Aug 87 22:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870806223002.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July and on mail received
in response to the last time I mailed this out (about two weeks ago).
If anyone doesn't see their response included, or thinks their favorite
issue is missing, please let me know and I will apologize for my error
and add it. I hope that we can use this file to help drive progress.
The major issues of object creation and class redefinition are not in
here, being handled individually.
The rest of this message is the file. Page separator characters don't
seem to go through, so I have replaced each with 16 equal signs.
This page is things that I think we agreed that we had decided
after the March meeting and before the July meeting.
27 May 87 call-next-method is allowed to take arguments, however it is
an error to give it arguments that would change the set of applicable
methods. I think we're saying this signals an error, and mentioning
that in some simple cases the lack of need for an error check can be
proved at compile time, but in general a run-time check is required.
Specify precisely the type of error signalling.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
Patrick agrees 7/29/87. It's in the document file now.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
Kempf agrees they should return the object. Moon isn't sure, because
defun, defvar, deftype, and defstruct return the name. As far as I can
tell every defxxx form in CLtL returns the name. The problem is that
we haven't admitted that defmethod has a name.
In July we decided (for the previous three) to return the object for
all CLOS defxxx functions (being inconsistent with Common Lisp, but
consistent within CLOS). The document file has been updated.
================
This page is a list of issues on which we should make decisions,
brought up by Danny. Where I saw responsive answers in the mail
(there were very few) I have edited them in. I've removed comments
that were purely editorial comments on the document.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, because
the representations might differ and existing instances might not
be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this, and Patrick and Jim agree.
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
In July we decided to defer this.
2 Aug 87 RPG offered to write a proposal.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
See additional discussion of class names below (2-13).
We need to decide whether class-name of an anonymous class is nil or
signals an error.
The concensus seems to be to return nil.
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. Then we said we'd discuss it further in the mail.
I think we agreed that the turning of two setf argument lists into one should
depend only on the argument lists, and not on the generic function object.
[My notes include an illegible comment, I think it means that I still hope
we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one. But maybe it means that
we will document it, but still have defmethod-setf so that most users
don't have to think about it (only users making setf methods "directly").]
p2-39 Arguments: "list of t's" should be replaced by "list whose elements are
the class named t" since get-method only takes specializers, not names of
specializers.
Agreed.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
p2-51 print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
I suppose the default method signals a condition of the same name?
Gregor will propose the details.
================
This page is a list I made in March, keyed by page numbers in the document.
Issues mentioned earlier, or that have since died, have been removed. I've
removed comments that were purely editorial comments on the document.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
2-13 class-named needs a new name for consistency. get-class would be wrong
because the other get-xxx functions aren't name operations. symbol-class is
the agreed name. It needs an environment argument to deal with the issue of
compile environment versus run-time environment. The errorp argument gets in
the way, because it's an optional argument--we could get rid of it, or we
could make both arguments keywords. I think we agree that symbol-class
should be setf'able, but can it only be set once for a given symbol or is it
allowed to change the symbol-to-class-object mapping?
Kempf: Need consensus on a general solution of the compile environment
issue before fixing individual functions such as symbol-class.
The symbol-to-class-object mapping should be changeable.
Bobrow: symbol-class should be setf'able.
Gregor: setf'able. Issue is consistency of symbol-class with class-name.
1) No class-name. 2) No consistency. 3) class-names returns a list of
names and setf of symbol-class maintains it. 2 is unreasonable.
I like 1 but 3 is good too.
(setf (class-named 'n1) nil) is how you undo the binding.
Note that this same analysis applies to generic-function-name and
setf of symbol-function and get-setf-generic-function.
Bobrow: I like 3.
Moon: class-names would need an environment argument too.
I guess any of these is okay but 2 is how everything else works.
I don't like undoing the binding by setting to NIL (CL Cleanup
may propose a general mechanism for undoing named definitions).
2-16 (slot-name form) should be allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
but it never finds its way into the document.
In July we rejected this. Since people keep assuming it, we have
to document explicitly that it is not allowed.
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
Kempf: it should signal an error.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-40 get-setf-generic-function needs an errorp, but it and ensure-generic-function
should be subsumed by get-generic-function which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Or was it called ensure-generic-function?
Gregor promised to mail out the proposal.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
================
Documented holes in chapters 1 and 2 of 87-002. We publicly promised
X3J13 that we would finish these and have a new draft of 87-003 by the
next meeting.
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
Document has been updated in draft.
Need Cleanup Committee proposals for fixes to the type system.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
This may not have been put into the document yet.
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
================
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Kempf: There may be a problem if the method invokes CALL-NEXT-METHOD.
[I wasn't able to understand his description of the problem -- Moon]
Ida: make-specializable seems to be missing
Gregor's proposal for ensure-generic-function will subsume this.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
To be resolved as part of the initialization protocol discussion.
Should we just flush multiple-value-prog2, as leading to more discussion
than is warranted by its simplification of the presentation of
define-method-combination?
Kempf: Yes.
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
The top level macros and functions should be part of LISP.
The internal functions specified for the sake of metaclass programming
can reside in CLOS.
If CLOS is an optional part of CL, are the symbols in the LISP package
even when the option is not present? Probably.
Should we flush defmethod-setf and friends in favor of function specs?
It probably turns out they could be just in the macros and not in the
underlying Lisp. The big issue is standardizing where the "new-value"
argument goes; but we may do that anyway (mentioned earlier in this file).
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe?
Kempf: I think we ought to keep DEFMETHOD-SETF, but use function specs (or
something like them) as the programmer interface to TRACE.
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
The fact that symbol-function (the user callable primitive) needs to
be split from the subprimitive for implementators that gets and sets
the "real" function definition of a symbol. This is so when a symbol's
function definition is a generic function object, the "real" definition
can be something that is easier for the implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
Kempf: I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations.
Moon: Right, the only standardization issue is making sure
SYMBOL-FUNCTION returns the generic function object, not something internal.
See earlier discussion of class-names (2-13), which affects symbol-function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor volunteered to send some mail about this.
CALL-NEXT-METHOD with no more methods should do something similar,
but not identical.
We could call a generic function like NO-MATCHING-METHOD, but it would
be better to signal a condition (assuming conditions are adopted into
Common Lisp). The error message should give some information about
the classes of the parameters, to help debugging.
Clarify that because class names and classes are type-specifiers, they can be
validly be used in THE special forms and in TYPE declarations. We forgot this
when we clarified that class objects can be used with TYPEP and SUBTYPEP.
July: agreed
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
Need to be able to get at the obsolete classes associated with a class,
to put methods on them.
Patrick has proposed.
Need discussion of how instances are transformed one step at a time
when a class has been redefined multiple times.
Not all of the "corrections and amendments" handed out at the March 1987
X3J13 meeting in Palo Alto have been put into the document yet. The
corrections are in but the amendments and the revised explanation of slot
inheritance are awaiting review by the group.
Kempf 29 Jul 87: There was no mention made of compile time optimization,
which I believe I made some initial proposals on in late April or early May.
I've been meaning to revisit them.
2-30: Note the third paragraph on p.2-30 of 87-002, speaking of signalling an
error when the arbitrary order of two methods affects the result. I suggest
that this error be mandatory instead of optional.
∂09-Aug-87 1514 Gregor.pa@Xerox.COM Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Aug 87 15:14:01 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 09 AUG 87 15:14:26 PDT
Date: Sun, 9 Aug 87 15:14 PDT
From: Gregor.pa@Xerox.COM
Subject: Miscellaneous decisions taken or to be taken
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870809151423.5.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
Date: Thu, 6 Aug 87 22:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July and on mail received
in response to the last time I mailed this out (about two weeks ago).
In the usual way, I have included only parts of your message on which
I am making specific comments. In several places I have sketched
proposal which were on my to do list. I am about to go away for a
week and don't have time between now and then to flesh these
proposals out, but I think they are fairly clear from the sketches.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on
that?
Patrick agrees 7/29/87. It's in the document file now.
I have it on my list of things to do to come up with a picture of how
all the standard classes (including standard type classes) are
organized. I have this on the whiteboard in my office now. In a
separate message, I will send out the name of a press file which
contains a simple version of such a picture. If people could FTP
that press file and try printing it, then I could now if its worth
trying to cast the whole picture in that format.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
Yes, I believe get-setf-generic-function should be a setfable form
with the same provision as Moon mentions. The way to think of
get-setf-generic-function is just like symbol-function and
symbol-class. (This may mean that it would be appropriate to rename
it to symbol-setf-generic-function.) Later in this message, I will
make some other comments which address this issue.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
I am not sure what you mean by this. Surely other non-destructive
operations would be legal as well. For example, one could implement
some sort of "tracing" :around method by having it get the list of
next methods, and calling each of their functions. But clearly it
would not be legal to rplaca or rplacd that list.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
See additional discussion of class names below (2-13).
As I said in another message, I don't believe class-name should be
setfable. symbol-class (nee class-named) should be setfable, it is
possible that it should update class-named as well, the details of
how that updating might work were the subject of my other message.
Even if we decide that class-name should return at most one name, I
think it is clear that a class can have more than one name. That is,
it is legal to use setf of symbol-class to make the multiple symbols
point to the same class.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument
that comes after all the other required arguments, and before the
optional, rest, and keyword arguments. Then we said we'd discuss it
further in the mail.
I think we agreed that the turning of two setf argument lists into one
should depend only on the argument lists, and not on the generic
function object.
[My notes include an illegible comment, I think it means that I still
hope we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one. But maybe it
means that we will document it, but still have defmethod-setf so that
most users don't have to think about it (only users making setf
methods "directly").]
I have several coments.
First, I believe it is very important that this operation only be a
function of the two lambda lists.
Second, I would rather the rules of this operation be documented.
That is, I would not be as happy if we just provided a function
(make-setf-method-lambda-list) which did the work. Providing that
function in addition to documenting its behavior might be a good idea
though.
Third, as we agreed, its fine with me to have it be the last required
argument. But I think we need to be careful how we word this.
Because we have to make it clear what happens in implementations
which have non-standard lambda-list-keywords.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
I suppose the default method signals a condition of the same name?
Gregor will propose the details.
slot-missing is a generic function which takes three required
arguments and an optional fourth argument. The three required
arguments are the class of the object, the object and the name of the
slot. The fourth argument is the new value for the slot if
slot-missing is being called by setf of slot-value. This set of
arguments allows people to define methods on the metaclass for
handling slot-missing. For example, a low performance implementation
of dynamic slots could work this way.
(defmethod slot-missing ((class dynamic-class) obj slot
&optional (nv nvp))
(if nvp
(set-dynamic-slot obj slot nv)
(get-dynamic-slot obj slot)))
The default method on slot-missing signals an error of the same name.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
I am pretty sure what we meant was we didn't want to have to worry
about the case where someone returns a closure that includes a call
to call-next-method, and then redefines the class or method structure
so that the closure would have to call different 'next methods'.
2-13 class-named needs a new name for consistency. get-class would be
wrong because the other get-xxx functions aren't name operations.
symbol-class is the agreed name. It needs an environment argument to
deal with the issue of compile environment versus run-time environment.
The errorp argument gets in
the way, because it's an optional argument--we could get rid of it, or we
could make both arguments keywords. I think we agree that symbol-class
should be setf'able, but can it only be set once for a given symbol or
is it allowed to change the symbol-to-class-object mapping?
Kempf: Need consensus on a general solution of the compile environment
issue before fixing individual functions such as symbol-class.
The symbol-to-class-object mapping should be changeable.
Bobrow: symbol-class should be setf'able.
Gregor: setf'able. Issue is consistency of symbol-class with class-name.
1) No class-name. 2) No consistency. 3) class-names returns a list of
names and setf of symbol-class maintains it. 2 is unreasonable.
I like 1 but 3 is good too.
(setf (class-named 'n1) nil) is how you undo the binding.
Note that this same analysis applies to generic-function-name and
setf of symbol-function and get-setf-generic-function.
Bobrow: I like 3.
Moon: class-names would need an environment argument too.
I guess any of these is okay but 2 is how everything else works.
I don't like undoing the binding by setting to NIL (CL Cleanup
may propose a general mechanism for undoing named definitions).
If this whole mess isn't an argument for a lisp-1 I don't know what
is. At this point I guess we need:
symbol-class
symbol-setf-generic-function
(both of the above need to be setfable)
(there needs to be a mechanism for making each unbound)
(we need to decide how they interact with class-name and
generic-function-name)
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
The current initialization proposal doesn't have constructors?
2-40 get-setf-generic-function needs an errorp, but it and
ensure-generic-function should be subsumed by get-generic-function
which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Or was it called ensure-generic-function?
Gregor promised to mail out the proposal.
I propose that we keep get-setf-generic-function, but that we rename it to
symbol-setf-generic-function. In addition, I propose that we do the
following:
ensure-generic-function, add-named-method and any other CLOS
function that takes the name of a generic function as an argument
can also take a list like (SETF <symbol>) which means the
setf-generic function for that argument.
I propose that ensure-generic-function do basically what
defgeneric-options and defgeneric-options-setf used to do except that
ensure-generic-function would be a function (that is it would
evaluate its arguments). This isn't a problem since
defgeneric-options didn't take any &body arguments anyways. The real
thing that needs to be worked out here is what happens if the generic
function already exists, but is different in some ways than the
description in the arguments to ensure-generic-function.
2-57 with-slots :prefix package problem; This was discussed in the mail
and then the ball was dropped. What's in the document is unworkable
because it depends on the dynamic value of *package* at macro-expansion
time, but Common Lisp doesn't guarantee anything about when
macro-expansion occurs. Moon would prefer to flush the :prefix option.
An alternative that was discussed was to use symbol-package of the
prefix, both here and in defclass accessor construction, as the package,
relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
I like the prefix option, although I agree that this is a serious
problem.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
What if by the time you actually run the body of the method, the slot
has an accessor. That is to say, what if you do the following:
(defclass foo () (a b c))
(defmethod bar ((o foo)) ;Put this in a file,
(with-slots (o) (list a b c))) ;compile and load it.
(defclass foo ()
(a b c)
(:accessor-prefix foo-))
(bar (make-instance 'foo))
Does this signal an error? It seems to me that the real problem with
this case is the same as the real problem with the above case. It
all hinges on exactly when macro-expansion time is and that is not
specified.
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
I believe it should signal an error to attempt to put a method on
more than one generic function. My model of this is that if you want
to do something like that, you can take one function, use it as the
method function of multiple methods, each of which would be on a
different generic function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor volunteered to send some mail about this.
This is a generic function like slot-missing. There is a generic
function NO-MATCHING-METHOD which is called with the generic function
as the first argument and the arguments to the generic function as
the remaining arguments. This allows people to defined method to
handle the no matching method case either on the class of the generic
function or on the individual generic function. The default method
for no-matching-method signals an error of the same type.
-------
∂10-Aug-87 1122 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Aug 87 11:21:44 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 10 Aug 87 11:14:59 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 10 Aug 87 11:14:33 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 10 Aug 87 12:15:19 pdt
Message-Id: <8708101815.AA15913@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Name That Class
In-Reply-To: Your message of Thu, 06 Aug 87 22:14:00 -0400.
<870806221457.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 12:15:15 MST
From: kempf%hplabsz@hplabs.HP.COM
> As far as I am concerned, any of these three would work. My objection
> to solution 3 is primarily that it is more complicated.
In addition to this objection to solution 3, another is that while other things
(particularly functions) can be multiply named, there
is currently no portable way in CL to get the name (or names) of
a function given a function definition object. If we are going to model
class object naming similarly to function naming (as the name SYMBOL-CLASS
seems to indicate) then we should probably be consistent with the way
functions are done, or suggest that a FUNCTION-NAME or a FUNCTION-NAMES
function be introduced which provides similar functionality; otherwise,
people may become confused. But see below for further thoughts.
> ....
> (setf (class-named 'n1) nil)
> #<Standard-Class N2 1>
> Is this really how we want to undo these bindings? Nothing else in Common
> Lisp I can think of works this way (storing nil). Also, a minor nit, CL
> requires that such a setf form return nil, not the former value.
> I think its easy to see how this whole thing would work for
> generic-function-name, symbol-function, setf of symbol-function,
> get-setf-generic-function and setf of get-setf-generic-function.
> Agreed. Note that (setf (symbol-function 'foo) nil) isn't how we do
> (fmakunbound 'foo) in CL currently.
Your observation about undoing bindings is correct, and, again, to maintain
consistency, CMAKUNBOUND would be the way do this if class name to
object binding is modelled on function name to object binding.
We seem to be slowly drifting towards using a name to object binding
for classes which is modelled on the way function name to object bindings
are handled. I wonder how useful the function model is for modelling
class name to object bindings. In particular, is this going to lead to
the proposal of a "class cell" like the "function cell" for a symbol?
Considering the controversy surrounding the latter, I certainly hope not.
Somehow, I would prefer a more object-oriented approach to resolving this
problem. Two ways which I can think of offhand are:
1) Have the class name be a SETFable slot in the class object. SETFing
a class object's name slot to NIL would be equivalent to making the class
anonymous, if we abide by the convention that asking for the name of
an anonymous class returns NIL (as was discussed in another note string).
2) Have the name to class object binding for an entire class be handled
by the metaclass protocol.
Of the two, I prefer the second one, since it gives some flexibility
for users wanting to define new metaclasses, and also gives some potential
for resolving the compile time name to object mapping, since the metaclass
can potentially control this, but perhaps in an implementation dependent
manner.
I'm willing to write up a proposal on this, if there is any interest.
Though I prefer a more object-oriented approach, I think it is important
that the name to object mapping issue be resolved in a way that is self
consistent and consistent with the rest of Common Lisp.
jak
∂10-Aug-87 1145 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Name That Class
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 10 Aug 87 11:45:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 152618; Mon 10-Aug-87 14:42:59 EDT
Date: Mon, 10 Aug 87 14:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Name That Class
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8708101815.AA15913@hplabsz.hpl.hp.com>
Message-ID: <870810144215.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 12:15:15 MST
From: kempf%hplabsz@hplabs.HP.COM
2) Have the name to class object binding for an entire class be handled
by the metaclass protocol.
Of the two, I prefer the second one, since it gives some flexibility
for users wanting to define new metaclasses, and also gives some potential
for resolving the compile time name to object mapping, since the metaclass
can potentially control this, but perhaps in an implementation dependent
manner.
I'm willing to write up a proposal on this, if there is any interest.
I don't understand how this could work. If one is given a class name and
one wants to find the corresponding class object, how do you know what
metaclass is relevant before you have found the class object?
∂10-Aug-87 1419 kempf%hplabsz@hplabs.HP.COM Re: TRACE Proposal (Version 1)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Aug 87 14:18:43 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 10 Aug 87 10:45:16 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 10 Aug 87 10:44:48 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 10 Aug 87 11:45:34 pdt
Message-Id: <8708101745.AA15689@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, masinter.pa@XEROX.COM
Subject: Re: TRACE Proposal (Version 1)
In-Reply-To: Your message of Thu, 06 Aug 87 14:10:00 -0400.
<870806141000.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 11:45:31 MST
From: kempf%hplabsz@hplabs.HP.COM
> A function-spec is either a symbol naming a function (i.e. a symbol
> whose global function cell is bound to a function definition object)
> or a list whose first element is a function specification type, and
> whose tail indicates which particular function of that type should
> be traced.
> The Cleanup subcommittee of X3J13 were discussing something similar
> a while back, starting from a different point. The DOCUMENTATION function
> of Common Lisp introduces the concept of "definition types", and this
> concept could be useful in other operations. For instance, it would be
A definition type would certainly be a nicer way of handling this. It
would unify how to indicate that a particular definition is wanted.
> Note: Another useful enhancement would be to support a :BREAK flag, like
> this:
> (:METHOD <spec> :BREAK)
> indicating that a break loop should be entered before and after the
> function executes.
> Here you see a conflict between lists as function-specs and lists as
> lists of options, in the arguments to TRACE. Because of this your proposal
> for TRACE is not compatible with what Symbolics currently does, but I don't
> think that's too important for us. We say that a list is a list of options,
> and if you want to trace a function whose name is a list, you have to do
> (TRACE (:function <function-spec> <options>...)). But all this really
> shows is that the syntax of TRACE is ridiculous. I usually ignore the TRACE
> function and trace things through a command interface. Anyway, for your
> proposal you have to decide between lists as function specs and lists as
> options; I don't think you can mix them freely as you proposed. Of course
> it would be a lot > e> asier if TRACE only traced one function at a time,
> then the rest of the form could be used for options. That would be a bit
> incompatible with CLtL.
An alternative would be to introduce a BREAK macro:
BREAK &REST {function-spec or definition}* [Macro]
having the obvious functionality. Such a "functional" interface would
avoid having to try indicating everything through one operation. I
just suggested the :BREAK option because this similar to how we currently
do it.
> TRACE-EXECUTION object &OPTIONAL env [Generic Function]
> I didn't completely understand this. It looks like there is some
> incoherence about whether TRACE is an operation on functions or on
> places in which you can store a function definition. In other words,
> does tracing a function redefine the function or alter the object that
> is the function's definition? In other words, does
> (defun foo () ...)
> (setq f #'foo)
> (trace foo)
> (funcall f)
> generate trace-output or not? We have to decide one way or the other.
> CLtL is obscure on this point.
As is usual in CLOS, the idea here was to split trace functionality into
two pieces a) a programmer interface (TRACE) b) a system level or
metaclass protocol function (TRACE-EXECUTION).
With reference to your example, certain implementations may support the
ability to modify function definition objects directly to allow trace
information to be inserted. Thus the FUNCALL in the example could be
traceable. As the base note suggested, these implementations could then
have a function spec (or definition type) for indicating that the function
should be trace through the fundef object rather than through the symbol.
Other implementations may only be able to trace though a wrapper on the
function symbol. The function spec or definition type would be used for
indicating to TRACE what to do, a corresponding TRACE-EXECUTION method
would contain the implementation dependent code to do it.
As to why go to the trouble of having an extra layer, consider a user
who wants to write a method or generic function class for remote procedure
calls. This user would like some way of handling debugging, and a generic
function in the metaclass protocol seems like the right way to do it.
A generic function would provide the system level interface for other
kinds of debugging functionality.
jak
∂11-Aug-87 1504 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Aug 87 15:03:36 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 11 Aug 87 15:01:11 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 11 Aug 87 15:00:34 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 11 Aug 87 16:01:15 pdt
Date: Tue, 11 Aug 87 16:01:13 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8708112201.AA26864@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Name That Class
In-Reply-To: Your message of Mon, 10 Aug 87 14:42:00 -0400.
<870810144215.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
I said:
Date: Tue, 11 Aug 87 16:01:12 MST
From: kempf@hplabsz
>> 2) Have the name to class object binding for an entire class be handled
>> by the metaclass protocol.
Moon replied:
> I don't understand how this could work. If one is given a class name and
> one wants to find the corresponding class object, how do you know what
> metaclass is relevant before you have found the class object?
and Gregor said (somewhat earlier):
>Even if we decide that class-name should return at most one name, I
>think it is clear that a class can have more than one name. That is,
>it is legal to use setf of symbol-class to make the multiple symbols
>point to the same class.
and Patrick said (even earlier):
>The environment argument will be necessary to address the compile
>environment problem. The term might be confusing, it is not necessary
>an environment like the &environment argument in a macro definition.
I've been rethinking this issue somewhat, and I think we need to consider
how class names will be used. I can see three ways in which
users may need to use class names:
1) In inheritance lists for indicating direct supers,
2) In parameter specializer lists for indicating that particular method
parameters are specialized to particular classes (or their subclasses),
3) For instantiation,
4) For general queries (i.e. system building-"Is this class there?", etc).
There will be more reasons for using class names if metaclass programming
is taken into account. Let's just consider these for the moment and ask
what would happen if a many to one mapping of classes to names (and
vice versa) were allowed.
If multiple names were allowed to be "bound" to a single class object,
then the function CLASS-NAME(S) could potentially return a list.
The function SYMBOL-CLASS (or CLASS-NAMED) could also return a list,
since, for any particular name, there could be multiple class
objects having it. That is, if we have FOO1 and FOO2 bound to two different
class objects, and the following is legal:
(setf (class-name foo1) 'baz)
(setf (class-name foo2) 'baz)
then the following:
(symbol-class 'baz)
should return a list with two elements, with the CAR EQ to FOO1 and the
CADR EQ to FOO2.
What would this mean for user code? For one thing, the following would be
ambiguous:
(defmethod doit ((x baz))
...
)
since there are now two possibilities for the class BAZ. One could argue
that this should mean that the method should be selected if X is
from either class, but that would be expanding the kind of parameter
specializer to boolean selection, and users may begin to demand something
like:
(defmethod doit ((x (or foo1-class foo2-class)))
...
)
which we may want to avoid. Of course, we could always demand that the
user put in the class object directly, to disambiguate, but names are
good for *something*, in this case, as a shorthand for not having to
say something like:
(defmethod doit ( (x (cadr (symbol-class 'baz))) )
....
)
The reason classes are different from functions is because function
definition objects don't have settable names. You can't say:
(setf (function-name fundef1) 'foo)
(setf (function-name fundef2) 'foo)
at least, not in portable Common Lisp (most implementations probably
allow this sort of thing internally). In addition, the inverse mapping
to SYMBOL-FUNCTION (from function definition objects to names, called
FUNCTION-NAME in the above example) is not defined.
With classes, the inverse mapping needs to be defined and settable, and
that is what is compilicating the issue. There are ways to hack around it,
designating one name the principle name, etc., but they all introduce more
machinery that I think most users will want.
Metaclasses could be used to allow multiple names per class only if
the name to class binding were restricted to one to one within a metaclass.
Across metaclasses, multiple names per class could be allowed.
The various ways this would affect the programmer interface are as follows:
1) SYMBOL-CLASS would require an optional metaclass argument, which
would default to STANDARD-CLASS. SYMBOL-CLASS would be used for general
queries, in addition.
2) Inheritance lists would be no problem, since supers must be of
the same metaclass anyway.
3) DEFMETHOD would require additional machinery to specify the metaclass
of the parameters. Possible choices are:
a) A DEFMETHOD option specifying that the parameters must be
from a particular metaclass. This will give problems with
mixing specializers, for example, if specializers of
metaclass STANDARD-TYPE-CLASS are mixed with those of
metaclass STANDARD-CLASS, as is likely.
b) The syntax of specialized lambda lists be expanded to include
some means of indicating that the class is of a particular
metaclass. This is more flexible, but syntatically clumsier.
Something like:
(defmethod doit ((x foo nonstandard-class) y x)
...
)
is what I have in mind. Defaulting to STANDARD-CLASS may help.
c) DEFMETHOD only works with parameter lists whose classes
are from a restricted set of metaclasses. STANDARD-TYPE-CLASS,
and STANDARD-CLASS are obvious candidates. A user wanting to
handle parameters of another metaclass would need to write
their own parameter list parser, and their own top level macro.
4) Instantiation via. MAKE-INSTANCE would require either:
a) An optional metaclass argument,
b) The argument would need to be the class object itself
rather than a symbol,
c) A symbol argument could default to STANDARD-CLASS.
I honestly think that even this is more machinery than most applications
programmers are going to need. Most users are simply going to use the
default metaclass, and won't want to have more than one name per class
or more than one class per name.
But, as Patrick has pointed out, the issue is more complex. The name
to class (or name to generic function) binding has an additional component,
namely the environment. What I think we *really* want is a way to have
the name to object binding be dependent on the environment as well.
This issue is more important than the issue of user level multiple
names per class (even for metaclass programming) since it directly
affects implementations which can't use virtual memory to segment
processing steps, and could adversely affect bootstrapping in any event.
As I mentioned in a previous note, I think this issue should be resolved
by a comprehensive, well thought out statement about the processing model
for the Concepts chapter. Then, individual functions which require
interface modifications should be modified. As Patrick mentioned in his
note, the environment need not be a CLtL environment; in fact, given
the second class status of environments in Common Lisp, it is hard
to see how it *could* be without some beefing up of what you can do
with them.
I'll leave it at that for this note. Summarizing, my feeling is that
allowing a multiple name per class object binding has some serious problems
for user level code, since the names of class objects are and
probably should be settable. I don't feel offering the functionality
to users is particularly important at this time, but if people want
it, then I think restricting the name to object mapping to be one to
one on a metaclass by metaclass basis is probably the right way to go.
More important is a resolution of the name to object mapping in different
processing environments, and this should probably be done in a comprehensive
manner, including generic functions also.
Jim Kempf kempf@hplabs.hp.com
∂13-Aug-87 0928 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Name That Class
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 13 Aug 87 09:20:00 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah09181; 13 Aug 87 11:56 EDT
Received: from ti-csl by RELAY.CS.NET id ag11477; 13 Aug 87 11:49 EDT
Received: from Jenner by tilde id AA15544; Thu, 13 Aug 87 10:22:32 CDT
Message-Id: <2764855505-13956774@Jenner>
Date: Thu, 13 Aug 87 10:25:05 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Cc: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>,
common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Name That Class
In-Reply-To: Msg of Tue, 11 Aug 87 16:01:13 pdt from Jim Kempf <kempf%hplabsz@hplabs.hp.com>
2) Inheritance lists would be no problem, since supers must be of
the same metaclass anyway.
That's not true, supers can be of other compatible metaclasses.
But, as Patrick has pointed out, the issue is more complex. The name
to class (or name to generic function) binding has an additional component,
namely the environment. What I think we *really* want is a way to have
the name to object binding be dependent on the environment as well.
This issue is more important than the issue of user level multiple
names per class (even for metaclass programming) since it directly
affects implementations which can't use virtual memory to segment
processing steps, and could adversely affect bootstrapping in any event.
As I mentioned in a previous note, I think this issue should be resolved
by a comprehensive, well thought out statement about the processing model
for the Concepts chapter. Then, individual functions which require
interface modifications should be modified. As Patrick mentioned in his
note, the environment need not be a CLtL environment; in fact, given
the second class status of environments in Common Lisp, it is hard
to see how it *could* be without some beefing up of what you can do
with them.
This is an entirely different issue from what you've been talking about.
Environments and metaclasses are orthogonal.
I'll leave it at that for this note. Summarizing, my feeling is that
allowing a multiple name per class object binding has some serious problems
for user level code, since the names of class objects are and
probably should be settable. I don't feel offering the functionality
to users is particularly important at this time, but if people want
it, then I think restricting the name to object mapping to be one to
one on a metaclass by metaclass basis is probably the right way to go.
I don't see what can be gained by having one namespace per metaclass. I think
it compromises modularity. When you list your supers in DEFCLASS, you
don't/shouldn't have to care what metaclass they belong to as long as they are
compatible with your metaclass.
Patrick.
∂17-Aug-87 2133 kempf%hplabsz@hplabs.HP.COM Environments, Naming, and CLOS (was Re: Name that Class)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 17 Aug 87 21:32:55 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 17 Aug 87 21:31:02 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 17 Aug 87 17:02:14 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 17 Aug 87 18:02:53 pdt
Message-Id: <8708180002.AA10001@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Environments, Naming, and CLOS (was Re: Name that Class)
In-Reply-To: Your message of Thu, 13 Aug 87 10:25:05 -0500.
<2764855505-13956774@Jenner>
Date: Mon, 17 Aug 87 18:02:50 MST
From: kempf%hplabsz@hplabs.HP.COM
> 2) Inheritance lists would be no problem, since supers must be of
> the same metaclass anyway.
> That's not true, supers can be of other compatible metaclasses.
I stand corrected. In the event of a name clash, some means
of disambiguating the name to class mapping would be needed.
One possiblility would be to extend the definition of "compatible"
to include "not having classes with the same name". Provided,
of course, that multiply named classes were seen to be such
an important feature that they should be included (which I
doubt).
>
>
> But, as Patrick has pointed out, the issue is more complex. The name
> to class (or name to generic function) binding has an additional component,
> namely the environment. What I think we *really* want is a way to have
> the name to object binding be dependent on the environment as well.
> This is an entirely different issue from what you've been talking about.
> Environments and metaclasses are orthogonal.
To the extent that the metaclass protocol takes into account
the processing environment, it may be possible for a particular
metaclass to do things differently in an environment from
others. For example, a metaclass supporting a language which
always resolves inheritance at compile time would need to
deal with the environment in a different way from the default
metaclass, where inheritance is resolved much later.
> I'll leave it at that for this note. Summarizing, my feeling is that
> allowing a multiple name per class object binding has some serious problems
> for user level code, since the names of class objects are and
> probably should be settable. I don't feel offering the functionality
> to users is particularly important at this time, but if people want
> it, then I think restricting the name to object mapping to be one to
> one on a metaclass by metaclass basis is probably the right way to go.
> I don't see what can be gained by having one namespace per metaclass. I thin> k>
> it compromises modularity. When you list your supers in DEFCLASS, you
> don't/shouldn't have to care what metaclass they belong to as long as they are
> compatible with your metaclass.
I agree. I can't see much use for allowing multiple names for
classes in the first place, since it requires more syntatic
machinery on the part of the programmer to indicate precisely
which class is meant in user level code. The point of the
metaclass proposal was that, if anywhere, that might be a
place where people might want to have multiple classes with
the same name. Suppose, for example, you want to have a
WINDOW class in CLOS and one in Smalltalk (or CommonObjects,
or Flavors, etc.). But Common Lisp provides packages for
seperating namespaces, and I think that's probably enough, as
long as you don't insist on exporting more than one WINDOW.
So you could have a FLAVORS::WINDOW and a SMALLTALK::WINDOW.
Personally, I think that this issue (multiple names for classes)
is a bit of a red herring. I just presented the metclass proposal
as an example of how it might make sense, but, as was pointed
out, additional machinery would be required at the syntatic
level to support it. The package system, despite its faults,
is the customary way of modularizing namespaces in Common Lisp,
and I think we should stick with that for user level code.
The issue of multiple names in different processing environments
is somewhat different. Because the package system is read time
only, and symbols map across compilation and loading into the
same package, the package system cannot be used to allow a
class of the same name to co-exist at compile time. Similarly
for methods. In order for a class or a set of classes and
their applicable methods to be compilable in the same file,
the CLOS metaclass protocol must insert enough information
into the compile time environment so that the methods can
be defined. At the extreme, the classes being compiled
could be simply be completely defined at compile time, but
this will, of course trash any existing definitions. This is
not a problem for implementations which an easily get new
virtual address spaces (modulo lengthening the time required
for compilation of a system), since most bootstrapping problems
could be solved by simply throwing away the environment and
getting a new one (there are probably some more subtle problems
here which I'm missing).
Is that a fair statement of the problem with environments
and naming?
As mentioned in previous notes, I think a section in Part I
about what CLOS needs in terms of processing environment
is important. I might add that the ANSI C standard has
about 8 pages of material on the processing environment at
the beginning. We are, of course, limited by what CLtL provides,
but I think, within that limit, we can probably be more
precise.
∂18-Aug-87 0820 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Names to Objects and Compiler-environment
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 18 Aug 87 08:20:03 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa00914; 18 Aug 87 11:18 EDT
Received: from ti-csl by RELAY.CS.NET id af11433; 18 Aug 87 11:08 EDT
Received: from dsg by tilde id AA23644; Tue, 18 Aug 87 09:44:15 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Mon, 17 Aug 87 16:14:24 CDT
Message-Id: <2765222127-2953787@Jenner>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Names to Objects and Compiler-environment
The name-to-object primitives we have in CLOS are:
Object Function Metaclass Implementation
dependent dependent
Class CLASS-NAME No Yes
Generic-function SYMBOL-FUNCTION No Yes
Method GET-METHOD Yes *
Name-to-method mapping implementation should be left to the metaclass writer
since it is tied up to the strategy of finding the applicable methods for method
discrimination and method combination. Besides name to object mapping, the
implementation provides some generic name services (source filename recording,
redefinition warnings...) that the metaclass wants/needs to use. This answers
the * sign in the above table. I believe that we need a portable interface to
those services.
Compile environment:
In order to avoid side-effecting the running environment during COMPILE-FILE,
the environment stores definitions in another namespace (compile environment).
The management of the environment(s) should be left to the implementation. All
our name-to-object functions are affected by this. We could make the
environment implicit and say that those function will return the object from the
"right environment" (SYMBOL-FUNCTION might work like that on some
implementations), but then it becomes hard to write GET-METHOD portably. I
propose that we make the environment explicit, passed as an argument to
CLASS-NAME, GET-METHOD, their SETF functions and related function such as
FIND-APPLICABLE-METHODS. I believe that CLOS should not know a whole lot about
environments so we don't require all the implementations currently supporting
compile-environment to change. Another issue is the dynamic extent of the
compile environment: The implementation control their lifetime. Their should
be a way for the implementation to signal the fact that a CLOS object no longer
needed because COMPILE-FILE is over.
Proposal(This would be part of the metaclass protocol):
1- Environment:
The implementation should provide some objects called environments. The
implementation controls their dynamic extent and their representation.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
The function (GET-RUNTIME-ENVIRONMENT) always
returns the runtime environment.
CLOS will use environment as a key into its data structures to mark an
object defined in a given environment (ie a method defined in a file
during COMPILE-FILE) or to look it up.
2- CLOS functions that must have an environment argument:
CLASS-NAMED and its SETF form,
ADD-METHOD,
GET-METHOD,
REMOVE-METHOD,
FIND-APPLICABLE-METHODS,
ENSURE-GENERIC-FUNCTION.
Questions:
Do we need to add an environment slot to STANDARD-CLASS, STANDARD-METHOD
and STANDARD-GENERIC-FUNCTION to get the environment they were defined in?
How do we provide a portable interface to those generic "name" services provided
by the implementation?
How does the implementation signal an object that it has been deleted from the
compiler environment?
The following might work but I am not sure:
ADD-TO-ENVIRONMENT OBJECT ENVIRONMENT. Tells the implementation that
the dynamic extent of OBJECT is the same as the dynamic extent of ENVIRONMENT.
DELETED-FROM-ENVIRONMENT OBJECT ENVIRONMENT this function is called by
the implementation on every object added to the environment by the call
to Add-to-environment before invalidating ENVIRONMENT. typically, It is
done at the end of COMPILE-FILE.
∂18-Aug-87 1136 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 18 Aug 87 11:35:40 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 18 Aug 87 08:51:16 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 18 Aug 87 08:50:43 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 18 Aug 87 09:51:23 pdt
Message-Id: <8708181551.AA15800@hplabsz.hpl.hp.com>
To: Kelley.pa@Xerox.COM
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of 05 Aug 87 17:48:00 -0700.
<870805-174848-5665@Xerox>
Date: Tue, 18 Aug 87 09:51:20 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry it's taken so long to respond.
>
> The CLOS proposed standard explicitly claims in general to obey the
> implicit inheritance - explicit override rule, but it does not for
I couldn't find a reference to "implicit inheritance - explicit override"
in Part 1 of the 87-002 spec. What page is it on?
> In as much as implicit inheritance is a sub-conscious assumption of
> application programmers, standard CLOS behaves in a counter intuitive
> manner.
In my opinion, inheritance should *never* be a sub-concious assumption.
It should be an explict design decision, made after considering
alternatives. If the supers are in a library to which the programmer
does not have source, then enough information should be given in the
library's documentation that the programmer can design accordingly.
Full analysis might not be required during a prototyping phase, but
nevertheless, the programmer should be familiar with the details of
the supers.
> (defclass border (object) (width))
> (defmethod close (b border) ...)
> (defclass window (object) (width))
> (defmethod close (w window) ...)
> (defclass bordered-window (border window))
> (setq b-window (make-instance 'bordered-window))
> (close b-window) ; with the current inheritance algorithm, only closes
> the border. Does not close the window.
> The following explores what could happen if the implicit inheritance -
> explicit override rule were followed in CLOS.
> (close b-window) would result in both the border and window close
> methods getting called because it inherits them implicitly and has not
> explicitly overridden them.
> With implicit inheritance a class may have in addition to multiple
> methods with the same name that all get called by one call, multiple
> occurrences of a slot with the same name that are manipulated in one
> operation so b-window would contain two slots named width.
> (setf (slot-value b-window width) 0)
> Would set both slots to 0.
Consider what would happen with a join superclass. In your example
OBJECT is a join superclass, since it is inherited through two supers
(WINDOW and BORDER) in BORDERED-WINDOW. For the supers above the join,
the base class gets two copies of slots, one through each branch through
the join class. There are two alternatives about what to do with the
two sets of slots:
1) Keep a seperate set for each branch of the join,
2) Merge them in some manner.
If the first approach is taken, then the object essentially has duplicate
copies of logically the same state. This approach was used in
CommonObjects, and is one aspect of CommonObjects which seems to bother
programmers the most. If the second approach is taken, it is possible
for some methods to be invoked more than once on the same set of
slots, making the method semantics for singly inherited and multiply
inherited cases different (see below for more discussion).
> A problem is what to do with the results of an operation on a slot name
> that refers to two or more slots or on a call that refers to two or more
> methods. Operating on these slots or methods that have not been
> overridden could be specified to return a "multiple-inheritance-result"
> object containing the multiple results.
This seems to me to be more complicated than most application programmers
will want. It would be hard to integrate with WITH-SLOTS, and would require
more syntatic machinery for setting or getting slots, pathnames to the
appropriate slot, or something similar. It seems inappropriate to
burden programmers with having to deal with such extra syntatic
machinery when slot merging will do the job most of the time.
> Any code that depended on the results from instances of singly inherited
> classes would not work correctly with instances of multiply inherited
> classes. (In the example above, any code that depended on the value
This is a general problem with linearizing multiple inheritance,
but most programmers who have used Flavors or CommonLoops are used to it,
and plan accordingly. It requires more knowledge about the supers
than for singly inherited languages, however.
The problem here is that every algorithm for multiple inheritance loses
somehow. If linearizing multiple inheritance is used, then the problem
with changing method semantics occurs. If tree-structured multiple
inheritance is used (where the entire tree of supers
is maintained, duplicating branches above joins) then duplicated state
occurs above join classes. If graph structured multiple inheritance is
used (where the graph of supers is maintained without duplication),
methods can be invoked multiple times on the same slot.
For a more detailed analysis, see Alan Snyder's paper in the last
OOPSLA proceedings.
What CLOS has tried to do (I think) is to provide Lisp programmers with
what they are most used to (i.e. codify existing practice), and to
do so in a manner which produces expected behavior most of the time.
If a programmer requires something out of the ordinary, then more time
and effort needs to be invested in learning more details, and, with
the metaclass protocol, much flexibility for changing inheritance
behavior is available. Where the CLOS inheritance algorithm could be
faulted, is that it handles the inability to linearize an inheritance
graph as an error, rather than providing hooks for the programmer
to override the default.
Alternatives to multiple inheritance for achieving the same effect
(i.e. maximum code reuse) are the subject for another basenote and
mailing list.
Jim Kempf kempf@hplabs.hp.com
∂18-Aug-87 1146 Moon@STONY-BROOK.SCRC.Symbolics.COM Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 11:45:56 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 215676; Tue 18-Aug-87 14:47:05 EDT
Date: Tue, 18 Aug 87 14:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Agenda for September meeting
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870818144639.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Sonya and I have put together a proposed agenda for the meeting
in September. Let's agree on what the agenda will be by the end
of this week.
Earlier I said that I wanted to leave by Friday noon, but in putting
together the agenda it became clear that 1 1/2 days wasn't enough time.
Hence we've written the agenda for two full days. Is that okay with
everyone?
Agenda for CLOS Meeting Sep 17-18 at Lucid in Menlo Park (first draft)
THURSDAY MORNING:
Discuss written proposals on major areas, circulated over the network
before the meeting and brought to the meeting in hardcopy. Spend no
more than 45 minutes on each proposal, determining yes, no, or needs
further discussion. Expected areas for proposals: object creation, new
draft of metaclass chapter, change-class, 1 or 2 others.
BREAK
Discuss a list of minor issues, to be circulated over the network before
the meeting and brought to the meeting in hardcopy. Moon will provide a
list (based on one that has already been circulated, updated from recent
mail), others will probably add to the list. Spend no more than 10
minutes on each issue, determining yes, no, or needs further discussion.
If yes, assign a volunteer to update the document accordingly.
LUNCH (let's keep this short)
Finish going through list of minor issues.
BREAK
Discuss proposals & issues that were determined to need further
discussion in the morning, in priority order. Objective is to decide
what will be in the document for the October X3J13 meeting. Things we
can't agree on here will be listed in the document as open issues.
END OF THURSDAY
Individuals may want to work on proposal drafts, writing tasks, etc.
during the evening.
FRIDAY MORNING:
Allocate remaining writing tasks and make sure we understand how we will
produce a document in time for the October X3J13 meeting, to be mailed
out around September 30. The objective should be for the tasks remaining
after the meeting breaks up to be purely editorial.
Prepare first drafts of material to go into the document, for all issues
where group effort is required. Each issue should have an individual
assigned as the leader for that issue, who writes the first draft which
is then criticized by others who are interested.
FRIDAY AFTERNOON:
Review what was written in the morning.
PREPARATION REQUIRED AHEAD OF TIME
Use network mail to finalize list of issues to be discussed and to get
everyone up to date on them.
Circulate proposals and issues list by the Friday before the meeting
(Sep 11).
Mail out hardcopies of the latest version of the 87-002 document
immediately (no further editing is planned, right?).
∂18-Aug-87 1522 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 15:22:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 215969; Tue 18-Aug-87 18:22:49 EDT
Date: Tue, 18 Aug 87 18:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
I would like to propose a small simplification of the short form of
define-method-combination.
Recognizing both an unqualified method and a method whose qualifier is
the name of the method combination type as primary methods seems
unnecessary and confusing. It muddles the issue of the identity of
a method (these are two separate methods with separate identities,
yet they do the same thing).
In addition, the qualifier is the name of the method combination type
but in the keyword package, so this is one more place where CLOS is
inventing symbols that don't appear in the source of the program, and
each time we do that it seems to cause trouble.
A possible drawback of this simplification is that it might make it
harder for users to understand the difference between "primary method"
and "unqualified method", since there won't be a counterexample to
the theory that the two terms are synonymous.
The specific document amendments are as follows, referring to 87-002:
2-27 Remove "A method with the keyword symbol with the same name as
{\it name\/} as its one qualifier is also defined to be a primary
method. Attaching this qualifier to a primary method documents that
this method is intended for use with an unusual form of method
combination and can make programs easier to understand."
2-30 Remove ":and" after "defmethod func".
Remove "(:and)" after "primary ()".
2-31 Remove "(:and)" after "methods ()".
Remove "(:and)" after "primary ()" [two places].
A related point is that we forgot to say in the document that a primary
method is required when using a method combination type defined with
the short form of define-method-combination, just as when using standard
method combination. We should say that explicitly.
∂18-Aug-87 1534 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Aug 87 15:34:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 AUG 87 15:33:17 PDT
Date: 18 Aug 87 15:31 PDT
From: Kelley.pa@Xerox.COM
Subject: Re: ECOOP Reaction to CLOS
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Tue, 18 Aug 87
09:51:20 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: Kelley.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870818-153317-1383@Xerox>
> The CLOS proposed standard explicitly claims in general to obey the
> implicit inheritance - explicit override rule, but it does not for
|I couldn't find a reference to "implicit inheritance - explicit
override"
|in Part 1 of the 87-002 spec. What page is it on?
I was refering primarily to page 1-7, the first paragraph both under
Inheritance of Methods and Inheritance of Slots and Slot Options.
Obeying implicit inheritance in general is claimed there (though
explicit override is implicit :-). The implication that the rule was
quoted as such in 87-002 was unintentionally misleading -- one too many
explicits in my original statement.
| ... the object essentially has duplicate
|copies of logically the same state. This approach was used in
|CommonObjects, and is one aspect of CommonObjects which seems to bother
|programmers the most. ...
If inheritance of methods with the same name in CommonObjects signals an
error, that is inconsistent with its slot inheritance.
|The problem here is that every algorithm for multiple inheritance loses
|somehow. ... If tree-structured multiple
|inheritance is used (where the entire tree of supers
|is maintained, duplicating branches above joins) then duplicated state
|occurs above join classes....
Based on the arguments in Snyder's OOPSLA 86 paper, I would claim this
problem is really a feature in disguise.
At any rate, presenting the effects of the proposed inheritance
algorithm for CLOS would be more understandable if in conjunction with
presenting the class ordering algorithm, violations of the "implicit
inheritance - explicit override" rule are clearly marked as such.
-- kirk
∂18-Aug-87 1615 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 18 Aug 87 16:15:06 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110793; Tue 18-Aug-87 19:09:52 EDT
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability. I think it's hard to understand what a method is doing if
you don't know how that method is going to be combined. Having the
qualifier there reminds you what kind of combination is going to be
used.
In order to eliminate the problem of having two separate methods that do
the same thing, I would rather make use of the qualifier be required
than forbidden.
I realize that this does not solve the problem of inventing symbols.
However, I think the benefit in readability outweighs this consideration.
∂18-Aug-87 1707 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ECOOP Reaction to CLOS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 17:07:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216070; Tue 18-Aug-87 20:06:44 EDT
Date: Tue, 18 Aug 87 20:06 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: ECOOP Reaction to CLOS
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <8707092024.AA22131@hplabsz.hpl.hp.com>,
The message of 6 Jul 87 14:30 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Some comments on characterizing the class precedence list algorithm.
In my comments I will refer to this set of classes (slots omitted):
(defclass a (b c w)) w x w y w x
(defclass aa (b c d w)) \ / \ / \/
(defclass b (w x)) b c d w
(defclass c (w y)) \ | / /
(defclass d (w x)) \ | / /
(defclass w ()) \ |/ /
(defclass x ()) aa
(defclass y ())
We've seen these classes before. By the rules in 87-002,
the CPL of a is (a b c w y x) and of aa is (aa b c d w x y).
Date: Thu, 9 Jul 87 13:24:38 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
The inheritance graph is searched depth first, left to
right, up to joins. Superclasses at joins are placed
in the class precedence list at the last occurance,
rather than the first, since such superclasses are
usually more general than their subclasses, and classes
at the end of the class precedence list should be more
general than those at the beginning. The qualitative
effect is to achieve a linearization of the inheritance
graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph.
A more detailed explantion should go into what can go wrong. The
Ducournau and Habib paper discusses this in a more formal way....
I like this informal way of explaining it, except that I never figured
out precisely what "up to joins" means, and depending on the
interpretation of that phrase, this explanation could be incorrect.
When the depth first walk of the graph for aa above encounters w above
c, that's a join. If it goes on to y, I don't think y is a join,
nevertheless y is not next in the CPL, x is.
Date: 06 Jul 87 1130 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
What would constitute an understandable characterization of the CPL?
Here are some examples of approaches:
1. We could have a set of constraints on the classes such that the CPL
is the unique total ordering satisfying those constraints.
If I understand the meaning of constraints as being additive, the
example above shows that it can't be done with constraints. Taking a
and adding d to make aa reverses the order of x and y, thus whatever
constraint was controlling the order of x and y must have been removed
when d was added. Perhaps this nonadditiveness is at the root of
people's difficulty in understanding the CPL computation.
2. We could have a set of inheritance situations such that when two
graphs of classes were inherited in particular ways, the new CPL was
predictable. For example, suppose we have 2 graphs, G1 and G2, with no common
classes except for the class named T and suppose that C1 and C2 are the
bottom-most classes of G1 and G2, respectively; then if a class C is
a subclass of C1 and C2 in that order, the classes in G1 precede the classes
in G2, and the classes in G1 are in the same order as they are in the CPL
for C1 and similarly for G2; T comes last.
Characterization #2 is in fact true, and it's not too hard to see why.
Suppose G1A is the second class in C1's class precedence list. After
topological sort has added C1 to C's cpl, the rule at the top of page
1-15 comes into play because either C2 or G1A could be next. The rule
selects G1A. By what amounts to induction, one can show that every
class in G1 will have a direct subclass to the right of C2's direct
subclass (C), and therefore every class in G1 will precede C2. I believe
one can also show that the classes in G1 will appear in the same order in
C's cpl as in C1's cpl. I don't think it's a coincidence that
characterization #2 is true, I think making it true was one of the
acceptance criteria for the CPL algorithm.
The problems occur just when G1 and G2 do have common classes (other
than T).
∂18-Aug-87 1728 Moon@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 17:28:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216083; Tue 18-Aug-87 20:29:21 EDT
Date: Tue, 18 Aug 87 20:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Names to Objects and Compiler-environment
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2765222127-2953787@Jenner>
Message-ID: <870818202904.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
I agree with the general thrust of what you're saying, but have some
nits to pick and a question to ask. I might have more to say on this
topic later.
Question: I had thought that environments referred only to the mapping
from names (Lisp symbols) to objects, but in saying that ADD-METHOD,
GET-METHOD, REMOVE-METHOD, and FIND-APPLICABLE-METHODS (not documented)
need an environment argument, I think you're saying that environments
also affect the mapping from generic-function objects to lists of
method objects. Is this correct? And is there any other kind of
mapping that they affect?
An environment of NIL should be defined to be synonymous with the
run-time environment, for programmer convenience.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
Does GET-CURRENT-ENVIRONMENT take no arguments? I believe that the
&environment argument to a macro expander is the only viable way for
the macro expander to know whether the code it's going to return has
its meaning defined in terms of the compile-environment or the run-time
environment. Thus I believe that the macro expander should pass its
&environment argument to GET-CURRENT-ENVIRONMENT. To avoid confusion,
we should either declare that these two kinds of environments are
identical, eliminating the need for GET-CURRENT-ENVIRONMENT, or else
we should find a new name for the CLOS kind of environment.
If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
some form of dynamic scoping, rather than lexical scoping, and you can
get scoping problems. Symbolics' implementation, and I believe TI's as
well, currently works this way, using the special variable
SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
environment they are working. The genesis of this is historical and
predates lexical scoping. This causes a number of subtle problems.
CLOS should not make this mistake.
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
I don't understand how adding GET-NEXT-ENVIRONMENT to the documented
interface is related to the issue of search lists. The implementation
can have those without anything special for them in the interface.
If there is searching, and I think there needs to be if only so the
compile environment can inherit from the run time environment, you need
a negative inheritance mechanism, so that the compile environment can say
such and such a method does not exist in the new version of this program
being compiled, even though it exists in the old version that is being
used to do the compilation.
How does the implementation signal an object that it has been deleted from the
compiler environment?
I would prefer that object deallocation be left to the garbage collector.
Are there any problems with that?
∂19-Aug-87 0632 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 06:32:28 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216238; Wed 19-Aug-87 09:33:33 EDT
Date: Wed, 19 Aug 87 09:32 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
Message-ID: <870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Initially, I had the same opinion you state -- that having the qualifier
in the defmethod form enhances readability, and that it was preferable
to make that qualifier be required rather than forbidden.
The reason for including the qualifier in the defmethod form is to
document the method (how it will be combined with other methods). But
we already provide a way to document a method, via the documentation
string. So now I'm in favor of having the methods be unqualified
instead of requiring that they be qualified.
Either of the new suggestions would be better than the way it is now,
where you can choose whether to include the qualifier or not.
∂19-Aug-87 0745 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 19 Aug 87 07:44:55 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110961; Wed 19-Aug-87 10:27:55 EDT
Date: Wed, 19 Aug 87 10:25 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Message-ID: <870819102506.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
I don't think the documentation string is adequate to produce the
results I'd like to see. In practice, I just don't believe that
programmers will, in fact, invariably (or even usually) remember to note
the method combination type in the documentation string for every method
that uses non-default method combination.
∂19-Aug-87 1020 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 10:20:10 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216470; Wed 19-Aug-87 13:21:20 EDT
Date: Wed, 19 Aug 87 13:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>,
<870819102506.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
Message-ID: <870819132057.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability.
Requiring the qualifier would satisfy my stated wants, provided that the
qualifier wasn't optional (so there was only one way to write a primary
method) and wasn't re-interned in the keyword package (so we aren't
inventing symbols).
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
∂19-Aug-87 1123 skeene@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 11:23:15 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216533; Wed 19-Aug-87 14:23:16 EDT
Date: Wed, 19 Aug 87 14:22 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Names to Objects and Compiler-environment
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2765222127-2953787@Jenner>
Message-ID: <870819142229.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
The name-to-object primitives we have in CLOS are:
Object Function Metaclass Implementation
dependent dependent
Class CLASS-NAME No Yes
Generic-function SYMBOL-FUNCTION No Yes
Method GET-METHOD Yes *
There's also GET-SETF-GENERIC-FUNCTION.
∂19-Aug-87 1349 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 19 Aug 87 13:49:28 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 111131; Wed 19-Aug-87 16:50:17 EDT
Date: Wed, 19 Aug 87 16:47 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870819132057.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870819164729.8.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Wed, 19 Aug 87 13:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
You seem to be setting up a hypothetical alternative, but I don't
understand what the alternative is. We don't have a language for
contracts.
It just seems to me that it's very hard to understand what a method is
doing, and easy to misunderstand it or be confused, if you don't see
what kind of combination is being employed. When you see a BEFORE
method, you know what that is. When you see an unqualified method, you
naturally assume that it's a primary method, and that (for example) what
it returns will be the result of the generic function call. But that's
not true if it's an AND-combined method, or worse yet a PROGN combined
method.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
I doubt I can come up with something much more convincing. It just
seems a lot clearer to me. (DanG mentioned to me, two days ago, that he
feels the same way.) In fact, I thought that the reason that qualifiers
for things like AND and OR were first (1980?) introduced was because we
felt they made the code clearer.
∂19-Aug-87 1455 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Names to Objects and Compiler-environment
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 19 Aug 87 14:55:12 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae09985; 19 Aug 87 17:46 EDT
Received: from ti-csl by RELAY.CS.NET id ac19836; 19 Aug 87 17:33 EDT
Received: from Jenner by tilde id AA03684; Wed, 19 Aug 87 15:19:37 CDT
Message-Id: <2765391661-13139657@Jenner>
Date: Wed, 19 Aug 87 15:21:01 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Names to Objects and Compiler-environment
In-Reply-To: Msg of Tue, 18 Aug 87 20:29 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Tue, 18 Aug 87 20:29 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Names to Objects and Compiler-environment
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
I agree with the general thrust of what you're saying, but have some
nits to pick and a question to ask. I might have more to say on this
topic later.
Question: I had thought that environments referred only to the mapping
from names (Lisp symbols) to objects, but in saying that ADD-METHOD,
GET-METHOD, REMOVE-METHOD, and FIND-APPLICABLE-METHODS (not documented)
need an environment argument, I think you're saying that environments
also affect the mapping from generic-function objects to lists of
method objects. Is this correct?
Yes, I want to do this primarily because It allows to be more efficient in terms
of structure copy. My file contains:
(defmethod speed ((thing my-ship))
.....)
;;some other things but no DEFCLASS for my-ship and
;;no DEFGENERIC-OPTIONS for speed.
During COMPILE-FILE I think it is unnecessary to copy the generic-function
or/and the class, to hold the method definition. What I had in mind was to add
the method to the runtime version of SPEED, in another namespace so a lookup for
this method in the runtime environment is not affected. I realize that we can
avoid this by copying the generic-function object to the compile environment,
but then we will have to copy some other objects (those side effected by the
defmethod) and end up having to copy a large portion of the world. Since we
tend to store first class object instead of names, we can't get enough leverage
off the name-to-object lookup. I tried to address this problem.
And is there any other kind of mapping that they affect?
I don't know, I can't think of any others but I might be ovelooking something.
An environment of NIL should be defined to be synonymous with the
run-time environment, for programmer convenience.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
Does GET-CURRENT-ENVIRONMENT take no arguments? I believe that the
&environment argument to a macro expander is the only viable way for
the macro expander to know whether the code it's going to return has
its meaning defined in terms of the compile-environment or the run-time
environment. Thus I believe that the macro expander should pass its
&environment argument to GET-CURRENT-ENVIRONMENT. To avoid confusion,
we should either declare that these two kinds of environments are
identical, eliminating the need for GET-CURRENT-ENVIRONMENT, or else
we should find a new name for the CLOS kind of environment.
If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
some form of dynamic scoping, rather than lexical scoping, and you can
get scoping problems. Symbolics' implementation, and I believe TI's as
well, currently works this way, using the special variable
SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
environment they are working. The genesis of this is historical and
predates lexical scoping. This causes a number of subtle problems.
CLOS should not make this mistake.
I agree with you. Passing the &environment argument to get-current-environment
is the best. I feared that the existing implementation would have to change too
much. If we do that, the compiler must tie up their compile-environment to the
macroexpand environment (which, to me, is a good thing ) and therefore must
change.
I don't think the two environments must be identical: a macroexpand
environment is free to change at each top level form, the compile environment
needs to be stay EQ for the extent of COMPILE-FILE. I would propose NAMESPACE
instead of environment.??
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
I don't understand how adding GET-NEXT-ENVIRONMENT to the documented
interface is related to the issue of search lists. The implementation
can have those without anything special for them in the interface.
If we want a metaclass to be written portably, to use environments, and be able
to implement the searching by itself, GET-METHOD should be able to be coded
like: search the method, using the specified environment as a tag and then using
the next environment and so forth. Does that make sense? I guess it is tied to
this assumption: [From my original message: Name-to-method mapping
implementation should be left to the metaclass writer since it is tied up to the
strategy of finding the applicable methods for method discrimination and method
combination.].
If there is searching, and I think there needs to be if only so the
compile environment can inherit from the run time environment, you need
a negative inheritance mechanism, so that the compile environment can say
such and such a method does not exist in the new version of this program
being compiled, even though it exists in the old version that is being
used to do the compilation.
I agree. (REMOVE-METHOD gf .... ENV) for example has to store in the place where
the metaclass will search that the method is not to be found in the context of
ENV. Does this negative inheritance need to be specified?
How does the implementation signal an object that it has been deleted from the
compiler environment?
I would prefer that object deallocation be left to the garbage collector.
Are there any problems with that?
The problem I see is that the objects are pointed to by more than the
environment: The direct-subclasses slot of a runtime class might point to a
compile-time class. The environment itself can be hold on to: A metaclass
writer can store object on an Alist whose key is the environment. I don't think
the garbage collector will be able to get rid of those objects.
Patrick.
∂19-Aug-87 1737 Gregor.pa@Xerox.COM meeting place
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Aug 87 17:37:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 19 AUG 87 17:36:55 PDT
Date: 19 Aug 87 17:36 PDT
From: Gregor.pa@Xerox.COM
Subject: meeting place
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870819-173655-3259@Xerox>
I just got back and haven't had a chance to really look through the
mail. The messages I thought I should try to answer right away were the
ones about meeting time and place.
Speaking for myself and Danny, we would rather have two entire days of
meetings.
Also speaking for Danny and myself, we would rather meet at PARC this
time. We met at Lucid last time, and parking and food are easier at
PARC. We can get a nice conference room in a part of the building where
we won't be bothered. I'll even try to get us one of those fancy
(Japanese) whiteboards that makes copies of what is written on it.
∂19-Aug-87 1830 Moon@STONY-BROOK.SCRC.Symbolics.COM meeting place
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 18:30:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216931; Wed 19-Aug-87 21:31:58 EDT
Date: Wed, 19 Aug 87 21:31 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: meeting place
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870819-173655-3259@Xerox>
Message-ID: <870819213135.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I don't care where we meet, but if it isn't Lucid someone should tell
Jan Zubkoff, since she has been making arrangements for a room.
∂20-Aug-87 0928 Moon@STONY-BROOK.SCRC.Symbolics.COM proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Aug 87 09:28:29 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217224; Thu 20-Aug-87 12:29:36 EDT
Date: Thu, 20 Aug 87 12:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: proposed syntactic cleanups in defmethod
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870820122915.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
We've noticed some problems with the CLOS syntax for defmethod,
especially when using methods on individuals, and in response I'd like
to propose three cleanups. Note that all of these changes are purely
syntactic; that is, they only affect the readability of programs, they
don't add or remove capabilities of the language. I hope this is a
minor issue that can be dealt with quickly.
The first problem has to do with the suggested compiler warnings
mentioned on CLtL p. 160 under the IGNORE declaration. Methods often
don't use some of their parameters for anything other than making the
method applicable for certain arguments to the generic function.
Consider this example
(defmethod additional-mail-headers ((host 'xerox.com))
(declare (ignore host))
'(:line-fold "No"))
One would prefer not to have to write the (declare (ignore host)).
This almost always happens with methods on individuals, but it can
also happen with methods on classes. Consider
(defmethod color ((e elephant))
(declare (ignore e))
'grey)
I propose that the DEFMETHOD macro be specified to "refer to" (in the
sense of CLtL p.160) each specialized parameter. This means that a
compiler warning will not occur regardless of whether the body of the
method does or does not refer to the parameter, and the declare ignore
in the above examples must be removed. This makes sense intuitively
if one regards the type check of the argument against the parameter
specializer as being part of the method; thus any specialized parameter
is referred to by the type check.
An interesting effect of this is that
(defmethod part-color ((e elephant) part)
'grey)
and
(defmethod part-color ((e elephant) (part t))
'grey)
are no longer synonymous, since the first gives a compiler warning
and the second does not. I think this is a feature, not a bug.
================
The second problem relates to the use of the single quote syntax (') for
methods on individuals. There are actually two problems here. One is
that that single character is easy to overlook. One of the most common
mistakes of beginning Lisp programmers is omitting quote marks or putting
them in the wrong place. Actually, it's not only beginning programmers
who do this. I still do it myself sometimes, and I believe I have seen
Danny Bobrow do it.
I believe the programmer who intended to write
(defmethod color ((e elephant))
'grey)
but accidentally wrote
(defmethod color ((e 'elephant))
'grey)
instead is going to have a lot of trouble figuring out what happened.
It would be better to make the latter form a syntactic error, so that
we can give a clear error message. We should use a different syntax for
methods on individuals. The quote mark is a cute hack, but I think we
can afford to use something slightly more verbose. Suggestion below.
The other problem with methods on individuals is that the current syntax
is awkward when the individual is anything other than a symbol or a
number, just because defmethod is using a special magic syntax instead
of a normal Lisp form. Returning to my first example, suppose hosts are
to be represented by CLOS objects rather than symbols. Instead of
writing
(defmethod additional-mail-headers ((host 'xerox.com))
'(:line-fold "No"))
I now have to write
(defmethod additional-mail-headers ((host '(parse-host "xerox.com")))
'(:line-fold "No"))
but this doesn't work, because the form (parse-host "xerox.com")
is not in a position to be evaluated. I can write
(eval `(defmethod additional-mail-headers ((host ',(parse-host "xerox.com")))
'(:line-fold "No")))
but that's grotesque. I can also write
(defmethod additional-mail-headers ((host '#.(parse-host "xerox.com")))
'(:line-fold "No"))
which works for this case, but #. has scoping problems exposed by the
next example. Suppose we're writing methods on individual numbers, but
rather than sprinkle numbers all over the code, we use defconstant, as
good style dictates. This is boiled down from a remote-procedure-call
example.
(defconstant begin-code 1)
(defconstant end-code 2)
(defconstant integer-code 3)
(defconstant float-code 4)
(defmethod decode (stream (opcode '#.begin-code))
... begin processing a message ...)
One problem with this occurs when using compile-file. CLtL isn't very
clear on whether #. evaluates in an environment in which those
defconstants have been evaluated. It's likely that the programmer has
to play some games with eval-when to make this work. This could be
fixed by tightening up the semantics of compilation in Common Lisp, but
a worse problem is that #. does not and can not respect lexical scoping.
Suppose we had
(let ((begin-code 1))
(defmethod decode (stream (opcode '#.begin-code))
... begin processing a message ...))
There is no way the #. can see the environment created by the LET
which is still being read in at the time the #. is processed.
It seems that it would make a lot more sense to put a regular Lisp form
in the parameter-specializer-name, scoped completely normally, and let
the defmethod macro (rather than the programmer) take care of any
special mechanism needed to evaluate with respect to the proper
environment, including compile-time defconstants. Common Lisp doesn't
currently standardize all the primitives needed to write that defmethod
portably, but I think that only strengthens the argument for making
defmethod worry about those issues, instead of making every programmer
worry about them.
So I'd like to see the syntax of an individual
parameter-specializer-name changed to use a different word instead of
QUOTE, and to use a form that evaluates to the object, instead of the
object itself. The form is evaluated at the time the method is defined;
it is not evaluated each time the generic function is called. I have
two suggestions for what word to use, one based on what test is being
performed and the second based on the Common Lisp type system:
(defmethod additional-mail-headers
((host (eql (parse-host "xerox.com"))))
'(:line-fold "No"))
(defmethod additional-mail-headers
((host (member (parse-host "xerox.com"))))
'(:line-fold "No"))
I mildly prefer EQL over MEMBER, but I thought I'd open up both
suggestions for discussion. Each of these suggests an obvious
generalization, EQL to other predicates and MEMBER to multiple
individuals, and the choice might be based on which generalization we
want people to think about, even if we don't propose to implement the
generalization.
================
The final issue has to do with parameter-specializers rather than
parameter-specializer-names, using the terminology of 87-002 page 1-18.
I think that adding QUOTE as a type-specifier to Common Lisp is both
unnecessary and confusing. (Yes, I know I suggested it. I was wrong.)
Instead, the parameter-specializer for a method on an individual should
be (MEMBER object), the type-specifier that Common Lisp already defines
for this purpose. Note that there is no particular reason why the
parameter-specializer should be the same as the parameter-specializer-name;
they're already not the same for methods on classes.
∂20-Aug-87 1010 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Aug 87 10:09:44 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217266; Thu 20-Aug-87 13:10:51 EDT
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870820131023.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on mail received in response to the last time I mailed this out
(two weeks ago). If anyone doesn't see their response included, or
thinks their favorite issue is missing, please let me know and I will
apologize for my error and add it. I hope that we can use this file as
part of the agenda for the September meeting. Let's try to resolve any
of these issues that can be resolved through the mail before that meeting.
Also, if I've marked an issue as agreed but you disagree, please speak up
now.
The rest of this message is the file. Page separator characters don't
seem to go through, so I have replaced each with 16 equal signs.
This file reflects Moon's understanding of the status of various CLOS issues,
concentrating on the more minor issues. The goal is to make sure that nothing
is overlooked, and especially to make sure that issues that have been brought up
and resolved are not forgotten before they get into the document. I've removed
most comments that were purely editorial comments on the document. I also
haven't tried to keep track of all the purely meta-object issues. I've edited
things to be as brief as possible.
All page references are to the 87-002 version of the CLOS document.
The file is divided into pages as follows:
0. This page of general outline
1. Documented holes in chapters 1 and 2 of 87-002
2. Things that have been already decided (but may not be in the document yet)
3. Issues with no apparent remaining disagreement
4. Small issues needing discussion
5. Issues whose status is unclear, maybe to be tabled
6. Big issues needing discussion, each on its own page
================
DOCUMENTED HOLES IN CHAPTERS 1 AND 2 OF 87-002
We publicly promised X3J13 that we would finish these holes and also have a new
draft of 87-003 by the next meeting (October).
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
Document has been updated in draft.
Need Cleanup Committee proposals for fixes to the type system.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
This may not have been put into the document yet.
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
================
THINGS THAT HAVE BEEN ALREADY DECIDED (BUT MAY NOT BE IN THE DOCUMENT YET)
27 May 87 call-next-method is allowed to take arguments, however it is an error
to give it arguments that would change the set of applicable methods. I think
we're saying this signals an error, and mentioning that in some simple cases the
lack of need for an error check can be proved at compile time, but in general a
run-time check is required. Specify precisely the type of error signalling.
10 June 87 The document has been updated with a discussion of how the standard
type classes are organized.
8/9/87 Gregor promised to draw a picture.
2-16 (slot-name form) is not allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
we have to document explicitly that it is not allowed.
The decision to reject (slot-name form) was made at the July meeting.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
p2-39 Arguments: "list of t's" should be replaced by "list whose elements are
the class named t" since get-method only takes specializers, not names of
specializers.
Agreed.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-54 in the Amendments: Clarify that because class names and classes are
type-specifiers, they can be validly be used in THE special forms and in TYPE
declarations. We forgot this when we clarified that class objects can be used
with TYPEP and SUBTYPEP.
July: agreed
================
ISSUES WITH NO APPARENT REMAINING DISAGREEMENT
1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Gregor says the metaclass protocol includes a predicate function that controls
whether the metaclass can be changed, which depends on whether the
representations differ and existing instances might not be transformable.
Some cross-reference to this should be added to the documentation of DEFCLASS.
1-15 to 1-22 Several errors in the formal description of class precedence and
method combination, pointed out by Jim Kempf on 4 August and 27 July, need to be
corrected. These are editorial changes only, that is, they make what the
document says conform to what I believe our intent to have been.
2-35 The argument order of the setf method ought to be documented here.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. It's important that this depends only on the two
lambda-lists, and not on any context such as the generic function object.
We still have defmethod-setf so that most users don't have to think about it
(only users making setf methods "directly").
The rule, carefully worded so as to work in the face of implementations with
non-standard lambda-list-keywords, is that the setf-lambda-list is inserted
into the normal lambda-list immediately after the last parameter-specifier
that precedes &optional, &rest, &key, or &aux. This is implemented by the
following function (should it be standardized as part of CLOS?):
(defun combine-setf-lambda-lists (lambda-list setf-lambda-list)
(do ((ll lambda-list (cdr ll))
(tail lambda-list))
((or (null ll) (member (car ll) '(&optional &rest &key &aux)))
(when (null ll)
(setq tail nil))
(append (ldiff lambda-list tail) setf-lambda-list tail))
(unless (member (car ll) lambda-list-keywords)
(setq tail (cdr ll)))))
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe? We're not going to allow that for
setf of generic functions.
2-50 Should we flush multiple-value-prog2, as leading to more discussion than is
warranted by its simplification of the presentation of define-method-combination?
Kempf: Yes.
2-51 It has been suggested that print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
2-54 slot-missing should be documented in chapter 2
Gregor:
slot-missing is a generic function which takes three required
arguments and an optional fourth argument. The three required
arguments are the class of the object, the object and the name of the
slot. The fourth argument is the new value for the slot if
slot-missing is being called by setf of slot-value. This set of
arguments allows people to define methods on the metaclass for
handling slot-missing. For example, a low performance implementation
of dynamic slots could work this way.
(defmethod slot-missing ((class dynamic-class) obj slot
&optional (nv nvp))
(if nvp
(set-dynamic-slot obj slot nv)
(get-dynamic-slot obj slot)))
The default method on slot-missing signals an error of the same name.
Symbol-function (the user callable primitive) needs to be split from the
subprimitive for implementors that gets and sets the "real" function definition
of a symbol. This is so when a symbol's function definition is a generic
function object, the "real" definition can be something that is easier for the
implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
Kempf: I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations.
Moon: Right, the only standardization issue is making sure
SYMBOL-FUNCTION returns the generic function object, not something internal.
See earlier discussion of class-names (2-13), which affects symbol-function.
Not all of the "corrections and amendments" handed out at the March 1987
X3J13 meeting in Palo Alto have been put into the document yet. The
corrections are in but the amendments and the revised explanation of slot
inheritance are awaiting review by the group.
================
SMALL ISSUES NEEDING DISCUSSION
1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens, but in August
Moon said he didn't like it and we should use MEMBER in parameter
specializers instead.
1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. What operations on that list should be
permitted?
- checking whether it's nil gives the desired feature
- checking its length
- doing something with list elements (presumably method objects)
- modifying the list is clearly out
- does the list have dynamic or indefinite extent?
This may be expensive enough that it can't substitute for
CALL-NEXT-METHOD-OR-NIL.
I think we're awaiting proposals on these two issues, as well as a
concensus on whether we need these features.
2-30: Note the third paragraph on p.2-30 of 87-002, speaking of signalling an
error when the arbitrary order of two methods affects the result. I suggest
that this error be mandatory instead of optional.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
Gregor: What if by the time you actually run the body of the method, the slot
has an accessor? It all hinges on exactly when macro-expansion time is and
that is not specified.
There are two issues here:
(1) Exactly when is the set of names scoped with with-slots determined?
(2) Exactly when is the presence or absence of an accessor for a name
determined?
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Kempf: There may be a problem if the method invokes CALL-NEXT-METHOD.
[I wasn't able to understand his description of the problem -- Moon]
Gregor: I believe it should signal an error to attempt to put a method on more
than one generic function. My model of this is that if you want to do
something like that, you can take one function, use it as the method function
of multiple methods, each of which would be on a different generic function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor:
This is a generic function like slot-missing. There is a generic
function NO-MATCHING-METHOD which is called with the generic function
as the first argument and the arguments to the generic function as
the remaining arguments. This allows people to define a method to
handle the no matching method case either on the class of the generic
function or on the individual generic function. The default method
for no-matching-method signals an error of the same type.
The error message should give some information about
the classes of the parameters, to help debugging.
CALL-NEXT-METHOD with no more methods should do something similar,
but not identical.
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
We need to decide whether class-name of an anonymous class is nil or
signals an error.
The concensus seems to be to return nil.
What does type-of return when applied to an instance of an anonymous
class?
Returning NIL is not valid by CLtL's definition of TYPE-OF.
The choices are either to return the class object itself or
the name of some superclass that has a name, T if necessary.
================
ISSUES WHOSE STATUS IS UNCLEAR, MAYBE TO BE TABLED
1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonable semantics for a GFLET and GFLABELS.
In July we decided to defer this.
2 Aug 87 RPG offered to write a proposal.
2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
Gregor: I am pretty sure what we meant was we didn't want to have to worry
about the case where someone returns a closure that includes a call
to call-next-method, and then redefines the class or method structure
so that the closure would have to call different 'next methods'.
Moon: Oh, so this is different from extent, because they could do that
redefinition before the method returns. So either we should say it
captures the set of next methods at a particular instant, or it's
undefined what happens if you redefine.
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
[no response to this so far, Moon should propose I guess]
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
Status depends on whether object-creation proposal includes constructors.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
To be resolved as part of the initialization protocol discussion.
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
The top level macros and functions should be part of LISP.
The internal functions specified for the sake of metaclass programming
can reside in CLOS.
If CLOS is an optional part of CL, are the symbols in the LISP package
even when the option is not present? Probably.
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
================
PREFIXED SYMBOL NAMES
These two issues appear to be related.
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelihood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
Gregor: I like the prefix option, although I agree that this is a serious
problem.
================
ENSURE-GENERIC-FUNCTION
A constellation of issues surrounding the mapping from generic function
names to generic function objects. This seems to be awaiting a proposal
to pull it all together.
1-18, 2-40 It is not specified whether get-setf-generic-function is setf-able.
Gregor: make it setf'able, it's just like symbol-function. Maybe
rename it to symbol-setf-generic-function?
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
Good reason to rename it to symbol-setf-generic-function.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
2-40 get-setf-generic-function needs an errorp, but it and get-generic-function
should be subsumed by ensure-generic-function which would do all the right things.
Gregor:
I propose that we keep get-setf-generic-function, but that we rename it to
symbol-setf-generic-function. In addition, I propose that we do the
following:
ensure-generic-function, add-named-method and any other CLOS
function that takes the name of a generic function as an argument
can also take a list like (SETF <symbol>) which means the
setf-generic function for that argument.
I propose that ensure-generic-function do basically what
defgeneric-options and defgeneric-options-setf used to do except that
ensure-generic-function would be a function (that is it would
evaluate its arguments). This isn't a problem since
defgeneric-options didn't take any &body arguments anyways. The real
thing that needs to be worked out here is what happens if the generic
function already exists, but is different in some ways than the
description in the arguments to ensure-generic-function.
The relevant options (referring to 2-42) seem to be:
:lambda-list -- method congruence issue
:generic-function-class -- covered below
:method-class -- are existing methods mutated?
Moon doesn't see any problem with changing these options:
:argument-precedence-order
:declare
:documentation
:method-combination
Gregor's e-g-f proposal, recovered from mail sent back in February,
and edited only slightly:
ensure-generic-function <symbol>
&key (generic-function-class
(class-named 'standard-generic-function))
(make-existing-function-default-p nil)
If symbol is fboundp to a generic-function of the same class as
generic-function-class then this function does nothing, and
returns the generic function object.
If symbol is fboundp to a generic-function of some other class, the
generic-function class changing protocol is followed, see chapter 3.
Use (class-named 'generic-function) to prevent changing the class
(is this right? does "of class" here mean typep or eq type-of?)
If symbol not foundp a generic function of generic-function-class is
created and put in symbol's function cell. There was some contention
over whether there should be a create-p argument to control this, or
the caller should do an fboundp test first.
If symbol is fboundp to a function, and make-existing-function-default-p
is not nil, a generic-function is created, put in the function cell, a
default method is added to the generic-function and the symbol's
previous function cell value is used as the function for the default
method.
If symbol is fboundp to a function and make-existing-function-default-p
is nil an error is signalled.
If symbol names a macro or a special form, an error is signalled.
Thus if this does not signal an error, it returns a generic function
object that is now the function definition of the symbol.
<symbol> can also be (setf <symbol>), as proposed later. How does the
caller do an fboundp test of this?
Feel free to change the names of the arguments. Note that this is a
function not a generic-function.
This needs to take additional arguments corresponding to all of the
arguments of defgeneric-options; see make-generic-function on 2-42.
================
CLASS NAMING ISSUE
[I have not yet summarized all the mail on this topic]
================
CLASS REDEFINITION
[I have not yet summarized all the mail on this topic]
================
COMPILER OPTIMIZATION
Kempf 29 Jul 87: There was no mention made of compile time optimization,
which I believe I made some initial proposals on in late April or early May.
I've been meaning to revisit them.
∂20-Aug-87 1525 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 20 Aug 87 15:18:52 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 20 Aug 87 13:23:58 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 20 Aug 87 13:22:33 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 20 Aug 87 14:23:19 pdt
Message-Id: <8708202023.AA19448@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Agenda for September meeting
In-Reply-To: Your message of Tue, 18 Aug 87 14:46:00 -0400.
<870818144639.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 14:23:16 MST
From: kempf%hplabsz@hplabs.HP.COM
> Earlier I said that I wanted to leave by Friday noon, but in putting
> together the agenda it became clear that 1 1/2 days wasn't enough time.
> Hence we've written the agenda for two full days. Is that okay with
> everyone?
Yes, this is fine.
> Discuss written proposals on major areas, circulated over the network
> before the meeting and brought to the meeting in hardcopy. Spend no
> more than 45 minutes on each proposal, determining yes, no, or needs
> further discussion. Expected areas for proposals: object creation, new
> draft of metaclass chapter, change-class, 1 or 2 others.
I'd like to put in debugging support under the "1 or 2 others" if nobody
has any strong objections. I'll rewrite the proposal based on the comments
Dave sent and resubmit to the network within the next week. The reason is,
our developers seem to need it.
> Mail out hardcopies of the latest version of the 87-002 document
> immediately (no further editing is planned, right?).
Yes, this is very definitely needed, as soon as possible.
-------------------------------------------------------------------------------
The rest of the agenda looks good to me. I have no particular preference
about where the meeting is held, just as long as the location is mailed
out ahead of time, so I can get there on time.
With regard to the spec documentation, I'd like to put in a vote for an ASCII
version to go on parcvax, along with the portable source, so people don't
have to be working in the dark with it. The ASCII version doesn't
necessarily have to be up to the current level of discussion and
decision within the committee (indeed, it probably shouldn't) but should
reflect approximately what is implemented. If there is some problem with
deTeXing it, we have some OCR software here which I'd be willing to give
a try at scanning it in with. Alternatively, Linda and Dick's paper from
ECOOP would be a possible source, although it's more of an overview (and
looks like it would probably be easier to scan in).
jak
∂21-Aug-87 0828 kempf%hplabsz@hplabs.HP.COM Re: proposed syntactic cleanups in defmethod
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 21 Aug 87 08:25:55 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Fri, 21 Aug 87 08:21:12 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 21 Aug 87 08:20:38 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 21 Aug 87 09:21:22 pdt
Message-Id: <8708211521.AA25991@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: proposed syntactic cleanups in defmethod
In-Reply-To: Your message of Thu, 20 Aug 87 12:29:00 -0400.
<870820122915.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 21 Aug 87 09:21:19 MST
From: kempf%hplabsz@hplabs.HP.COM
Proposal 1:
> I propose that the DEFMETHOD macro be specified to "refer to" (in the
> sense of CLtL p.160) each specialized parameter. This means that a
> compiler warning will not occur regardless of whether the body of the
> method does or does not refer to the parameter,
I support this proposal. I think a good case was made for it.
Proposal 2:
> So I'd like to see the syntax of an individual
> parameter-specializer-name changed to use a different word instead of
> QUOTE, and to use a form that evaluates to the object, instead of the
> object itself. The form is evaluated at the time the method is defined;
> it is not evaluated each time the generic function is called. I have
> two suggestions for what word to use, one based on what test is being
> performed and the second based on the Common Lisp type system:
I feel vaguely uneasy about this proposal. Part of the reason is because,
as rpg more forcefully stated somewhat earlier, I do not much like the idea
of having quoted objects as specializers in the first place.
The reason for this is as follows. One could view quoted objects as being
a kind of restricted subrange type. Allowing quoted objects means that users
can define methods which discriminate on individual FIXNUMs or arrays, but
disallowing subranges means they can't define methods which discriminate on
all FIXNUMs or arrays of a particular size.
One could argue that this is rather an argument for allowing subranges than for
disallowing quoted objects, but I believe that subranges are a distinctly
different kind of thing. In fact, subranges are a kind of type
parameterization, since certain parameters must be supplied at the time the
type is instantiated (as opposed to when an instance is created) and these
parameters are usually of a nature which constrain instances in some manner.
Following through on the FIXNUM example, FIXNUMs can be viewed as an
instance of a more general type, RESTRICTED-INTEGER, which requires a
parameter indicating upper and lower bounds on the size of instances.
Similarly, an individual FIXNUM can be viewed as a member of the type (EQL x).
That said, I think Moon's ADDITIONAL-MAIL-HEADER example:
> (defmethod additional-mail-headers ((host 'xerox.com))
> '(:line-fold "No"))
indicates how quoted objects as specifiers might be useful. But one could
just as well write:
(defmethod additional-mail-headers ((host symbol))
(case host
.... ;;various other possibilites
( 'xerox.com '(:line-fold "No") )))
Embedded CASE statements suffer the disadvantage that, when changes are
made (for example, adding a new host), then an additional branch must
be added or deleted everywhere. But, with quoted objects as parameter
specifiers, adding an additional case requires adding new method
definitions anyway, so I have trouble seeing any gain as opposed to the
loss of consistency cited above.
Classes could be used to generalize the mail example:
(defclass host-name ()
(
(name
:type symbol
:accessor NIL
:initform NIL
)
)
(:reader-prefix NIL))
(defmethod print-object ((object host-name) stream)
(print (name object) stream))
;;;Various other methods for dealing with host names
(defmethod additional-mail-headers ((host host-name))
(case (name host)
.... ;;various other possibilites
( 'xerox.com '(:line-fold "No") )))
Modifications to the host tables would still require adding another branch
to all CASEs, but methods operating on instances of HOST-NAME are likely
to be grouped together, and thus the difference between modifying a CASE
and adding an additional method is not large. After all, I don't think the
point of CLOS was to completely eliminate the need for CASE statements, but
rather to provide users a way of constructing code with generalizes
behaviors and structures.
So I'd actually prefer to eliminate quoted objects entirely.
> I mildly prefer EQL over MEMBER, but I thought I'd open up both
> suggestions for discussion. Each of these suggests an obvious
> generalization, EQL to other predicates and MEMBER to multiple
> individuals, and the choice might be based on which generalization we
> want people to think about, even if we don't propose to implement the
> generalization.
If the above arguments don't sound convincing, or people just don't have
the energy and want to stick with what we already have, then I'd prefer
introducing some kind of new symbol, rather than using either of these.
The reason is because I'd rather avoid having people generalize, since
either of the generalizations lead in directions which I don't think
we're prepared to address. Something like SINGELTON would be a possibility:
(defmethod additional-mail-headers ((host (singleton (parse-host "xerox.com"))))
'(:line-fold "No"))
Proposal 3:
> The final issue has to do with parameter-specializers rather than
> parameter-specializer-names, using the terminology of 87-002 page 1-18.
> I think that adding QUOTE as a type-specifier to Common Lisp is both
> unnecessary and confusing. (Yes, I know I suggested it. I was wrong.)
I agree with this (modulo my misgivings about quoted objects as
specializers in the first place); however, again I think that some specific
other symbol (like SINGLETON) would be more appropriate.
∂22-Aug-87 0004 Masinter.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Aug 87 00:04:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 AUG 87 00:04:47 PDT
Date: 22 Aug 87 00:04 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Fri, 21 Aug 87
09:21:19 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870822-000447-6288@Xerox>
To clarify, are you proposing that:
(dolist (x *broken-mail-hosts*)
(defmethod additional-mail-headers ((host (singleton (parse-host
x))) '(:line-fold "No")))
be a reasonable way to assign individual methods to, say, a large number
of individuals?
Implementations will have to be careful to allow objects which have
individual methods to be GCd, won't they?
∂22-Aug-87 0033 Masinter.pa@Xerox.COM Re: TRACE Proposal (Version 1)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Aug 87 00:33:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 AUG 87 00:32:02 PDT
Date: 22 Aug 87 00:31 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: TRACE Proposal (Version 1)
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Mon, 10 Aug 87
11:45:31 MST
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870822-003202-6311@Xerox>
I've managed to convince myself that definition types (which are
primarily for the use of DOCUMENTATION, and a general, programmatic way
of "undoing" a DEFmumble), are pretty much independent of "function
specs", which are handles on ways of getting at things which might have
breakpoints or tracepoints associated with them.
What I'm saying is that you should go ahead with your proposal for
function-specs in trace/break without worrying about any conflict from
the definition-type proposal which I have not finished writing.
∂22-Aug-87 1837 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Aug 87 18:37:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 218771; Sat 22-Aug-87 21:38:25 EDT
Date: Sat, 22 Aug 87 21:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: proposed syntactic cleanups in defmethod
To: Masinter.pa@Xerox.COM
cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870822-000447-6288@Xerox>
Message-ID: <870822213731.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Aug 87 00:04 PDT
From: Masinter.pa@Xerox.COM
To clarify, are you proposing that:
(dolist (x *broken-mail-hosts*)
(defmethod additional-mail-headers
((host (singleton (parse-host x))))
'(:line-fold "No")))
be a reasonable way to assign individual methods to, say, a large number
of individuals?
Yes.
Implementations will have to be careful to allow objects which have
individual methods to be GCd, won't they?
Not my department. Any form of individual methods has this problem.
∂24-Aug-87 1146 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 24 Aug 87 11:46:12 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 24 Aug 87 11:41:54 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 24 Aug 87 11:41:21 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 24 Aug 87 12:42:06 pdt
Message-Id: <8708241842.AA11723@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of Tue, 18 Aug 87 20:06:00 -0400.
<870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 24 Aug 87 12:42:03 MST
From: kempf%hplabsz@hplabs.HP.COM
In <870818-153317-1383@Xerox> kirk writes:
>At any rate, presenting the effects of the proposed inheritance
>algorithm for CLOS would be more understandable if in conjunction with
>presenting the class ordering algorithm, violations of the "implicit
>inheritance - explicit override" rule are clearly marked as such.
Yes, the description in Part 1 of the spec should contain proper
documentation of how slot and class options are default inherited.
In <870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM> Moon writes:
> Some comments on characterizing the class precedence list algorithm.
> In my comments I will refer to this set of classes (slots omitted):
> (defclass a (b c w)) w x w y w x
> (defclass aa (b c d w)) \ / \ / \/
> (defclass b (w x)) b c d w
> (defclass c (w y)) \ | / /
> (defclass d (w x)) \ | / /
> (defclass w ()) \ |/ /
> (defclass x ()) aa
> (defclass y ())
The class a seems to be missing from the diagram, but I'll refrain
from trying to include it, since the result is more confusing that
enlightening.
> We've seen these classes before. By the rules in 87-002,
> the CPL of a is (a b c w y x) and of aa is (aa b c d w x y).
> Date: Thu, 9 Jul 87 13:24:38 pdt
> From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
> The inheritance graph is searched depth first, left to
> right, up to joins. Superclasses at joins are placed
> in the class precedence list at the last occurance,
> rather than the first, since such superclasses are
> usually more general than their subclasses, and classes
> at the end of the class precedence list should be more
> general than those at the beginning. The qualitative
> effect is to achieve a linearization of the inheritance
> graph, with more specialized classes at the head of
> the class precedence list and more general classes at
> the tail, keeping together groups of classes which occur
> together in the inheritance graph.
> I like this informal way of explaining it, except that I never figured
> out precisely what "up to joins" means, and depending on the
> interpretation of that phrase, this explanation could be incorrect.
> When the depth first walk of the graph for aa above encounters w above
> c, that's a join. If it goes on to y, I don't think y is a join,
> nevertheless y is not next in the CPL, x is.
w is, indeed, a join class, since there is more than one line
of inheritance coming out of it. The definition of a join I had in
mind is a class which contributes two or more subclasses to the
CPL calculation. y is not a join, because there is only one line of
inheritance coming from it (namely y->c->aa). x is also a join, because
there are two lines of inheritance coming from it (namely x->b->aa
and x->d->aa). If we follow the explanation, then, after including
w, we use the local precedence ordering to select x as the next
class to include. In this case, the local precedence ordering takes
priority over other rules and x is included. y is then included after
x.
So a more accurate statement would be:
Define a join class as a superclass which contributes
two or more subclasses to a CPL calculation. Define
the base class as the class for which the CPL calculation
is being made. To calculate the CPL, the inheritance graph
is searched depth first, left to right, up to joins, starting
with the base class. Join superclasses are placed in the class
precedence list at the last occurance, rather than the first,
since such superclasses are usually more general than their
subclasses (from the base class's point of view),
and classes at the end of the class precedence list should be more
general than those at the beginning. After a join class has
been inserted, the local precedence ordering for the join
class is used to start the left to right search again above
the join. The qualitative effect is to achieve a linearization
of the inheritance graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph (i.e. maintaining local
precedence).
This a a bit more complicated than the original, but more accurate,
I think. Some words about failures to linearize and an example would
also be helpful.
∂24-Aug-87 1254 LGD updated spec on SAIL
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have made a few minor edits to the drafts of the concepts and functions
chapters that Sonya put out on SAIL last month. The only changes of note
here are some corrections to the new standard-type-class/superclasses
table in the section "Integrating Types and Classes."
I also tweaked the macros file so that it now prints "Draft" and the date,
so that we can keep our hardcopy drafts straight while we work.
There are also new .dvi files available.
--lgd
∂24-Aug-87 1304 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 24 Aug 87 13:04:27 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 24 Aug 87 13:04:04 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 24 Aug 87 13:03:41 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 24 Aug 87 14:04:22 pdt
Message-Id: <8708242004.AA12343@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of Mon, 24 Aug 87 12:42:03 -0700.
<8708241842.AA11723@hplabsz.hpl.hp.com>
Date: Mon, 24 Aug 87 14:04:19 MST
From: kempf%hplabsz@hplabs.HP.COM
> Define a join class as a superclass which contributes
> two or more subclasses to a CPL calculation. Define
> the base class as the class for which the CPL calculation
> is being made. To calculate the CPL, the inheritance graph
> is searched depth first, left to right, up to joins, starting
> with the base class. Join superclasses are placed in the class
> precedence list at the last occurance, rather than the first,
> since such superclasses are usually more general than their
> subclasses (from the base class's point of view),
> and classes at the end of the class precedence list should be more
> general than those at the beginning. After a join class has
> been inserted, the local precedence ordering for the join
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
> class is used to start the left to right search again above
↑↑↑↑↑
> the join. The qualitative effect is to achieve a linearization
> of the inheritance graph, with more specialized classes at the head of
> the class precedence list and more general classes at
> the tail, keeping together groups of classes which occur
> together in the inheritance graph (i.e. maintaining local
> precedence).
After I mailed this I realized that the ↑ underscored section should read:
the local precedence ordering for the join class's leftmost occuring
subclass
So integrating, and making a couple of other minor changes, gives:
Define a join class as a superclass which contributes
two or more subclasses to a CPL calculation. Define
the base class as the class for which the CPL calculation
is being made. To calculate the CPL, the inheritance graph
is searched depth first, left to right, up to joins, starting
with the base class. Join superclasses are placed in the class
precedence list at the last (rightmost) occurance, rather than
the first (leftmost), since such superclasses are usually more
general than their subclasses (from the base class's point of view),
and classes at the end of the class precedence list should be more
general than those at the beginning. After a join class has
been inserted, the local precedence ordering from the first
(leftmost) subclass of the join class is used to start the
left to right search again above the join. The qualitative effect
is to achieve a linearization of the inheritance graph, with
more specialized classes at the head of the class precedence list
and more general classes at the tail, keeping together groups of
classes which occur together in the inheritance graph
(i.e. maintaining local precedence).
∂24-Aug-87 1644 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: proposed syntactic cleanups in defmethod
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Aug 87 16:44:29 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa02900; 24 Aug 87 19:45 EDT
Received: from ti-csl by RELAY.CS.NET id ag16441; 24 Aug 87 19:34 EDT
Received: from Jenner by tilde id AA27526; Mon, 24 Aug 87 15:17:23 CDT
Message-Id: <2765823344-1583937@Jenner>
Date: Mon, 24 Aug 87 15:15:44 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: proposed syntactic cleanups in defmethod
In-Reply-To: Msg of Thu, 20 Aug 87 12:29 EDT from "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
I propose that the DEFMETHOD macro be specified to "refer to" (in the
sense of CLtL p.160) each specialized parameter. This means that a
compiler warning will not occur regardless of whether the body of the
method does or does not refer to the parameter, and the declare ignore
in the above examples must be removed. This makes sense intuitively
if one regards the type check of the argument against the parameter
specializer as being part of the method; thus any specialized parameter
is referred to by the type check.
Sounds good.
So I'd like to see the syntax of an individual
parameter-specializer-name changed to use a different word instead of
QUOTE, and to use a form that evaluates to the object, instead of the
object itself. The form is evaluated at the time the method is defined;
it is not evaluated each time the generic function is called.
I think it is a very good idea.
I mildly prefer EQL over MEMBER, but I thought I'd open up both
suggestions for discussion. Each of these suggests an obvious
generalization, EQL to other predicates and MEMBER to multiple
individuals, and the choice might be based on which generalization we
want people to think about, even if we don't propose to implement the
generalization.
I don't like MEMBER because it looks too much like the CLtL type
specifier and lots of people will think that they can discriminate on
multiple individuals. I am neutral on EQL versus another name as Kempf
suggested.
Patrick.
∂24-Aug-87 1701 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: short form of define-method-combination
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Aug 87 17:01:33 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aj02900; 24 Aug 87 19:46 EDT
Received: from ti-csl by RELAY.CS.NET id ao16441; 24 Aug 87 19:36 EDT
Received: from Jenner by tilde id AA28861; Mon, 24 Aug 87 16:18:11 CDT
Message-Id: <2765827013-1804390@Jenner>
Date: Mon, 24 Aug 87 16:16:53 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: short form of define-method-combination
In-Reply-To: Msg of Wed, 19 Aug 87 13:20 EDT from "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Date: Wed, 19 Aug 87 13:20 EDT
From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Subject: short form of define-method-combination
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability.
Requiring the qualifier would satisfy my stated wants, provided that the
qualifier wasn't optional (so there was only one way to write a primary
method) and wasn't re-interned in the keyword package (so we aren't
inventing symbols).
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
The fact that we have two ways of defining primary methods for flavors
is a major source of confusion. I got lots of questions about it. I am
glad that David Proposes to rectify things. I would be in favor of
omitting the qualifier, but if Dan objects to it, then requiring the
qualifier is OK too. To me, the important thing is that the primary
methods have all the same syntax and that we don't end up with two
primary methods for one set of specializers.
Patrick.
∂26-Aug-87 1916 Gregor.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Aug 87 19:16:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 26 AUG 87 19:15:44 PDT
Date: 26 Aug 87 19:15 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 20 Aug 87 12:29 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870826-191544-1414@Xerox>
I have certainly been bothered by the same problems with defmethod
syntax you address, but I am not sure about all of these solutions. What
is bothering me is that while they all provide convenience, they make
the defmethod form itself more complicated. I haven't yet made my mind
up, but I thought I would send out a message to at least say something,
since you said you hoped it could be resolved quickly.
The proposal to make defmethod forms, which actually name specializers
for arguments, refer to those arguments certainly would be convenient.
There are a lot of cases in PCL code where I could remove declare
ignores. But it makes the defmethod story more complicated.
Particularly, if arguments which are not specialized are also refered
to. I am not sure this is worth the tradeoff? But I am not sure it
isn't either.
The second proposal (to evaluate the argument to an EQL or ' specializer
at load time) addresses a much more real problem. In paricular, without
this, its not possible to use call-next-method inside of methods on
individuals. That probably makes this worth doing, even it it makes the
defmethod story more complex.
I have no particular opinion on the third proposal.
I would like there to be a simple, clean story which can be used to
correspondence between any given defmethod form, and a call to
add-method, make-instance and ensure-generic-function. Thats what makes
defmethod nice syntax for add-method the same way defun is nice syntax
for setf of symbol-function.
∂26-Aug-87 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 Aug 87 20:33:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 221804; Wed 26-Aug-87 23:34:54 EDT
Date: Wed, 26 Aug 87 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: proposed syntactic cleanups in defmethod
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870826-191544-1414@Xerox>
Message-ID: <870826233424.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 26 Aug 87 19:15 PDT
From: Gregor.pa@Xerox.COM
I would like there to be a simple, clean story which can be used to
correspondence between any given defmethod form, and a call to
add-method, make-instance and ensure-generic-function. Thats what makes
defmethod nice syntax for add-method the same way defun is nice syntax
for setf of symbol-function.
I agree that this is desirable. I don't think the changes I proposed make
the story more or less complicated than it was before. For example,
evaluating the specification of an individual rather than quoting it only
shows up as evaluating or quoting a particular position in the form resulting
from expansion of defmethod, I would expect.
Since I'm not sure I understand how these meta-level functions are intended
to be used, and since I have never seen the simple clean story written down,
I don't think I am competent to write out the details of how the expansion
of defmethod would be affected by my proposed changes. Gregor, perhaps you
could take a crack at it?
∂27-Aug-87 0952 kempf%hplabsz@hplabs.HP.COM Solutions to Name/Object Mapping for Generic Functions
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 27 Aug 87 09:52:00 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 27 Aug 87 09:51:04 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 27 Aug 87 09:50:38 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 27 Aug 87 10:51:23 pdt
Message-Id: <8708271651.AA07090@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Solutions to Name/Object Mapping for Generic Functions
X-Mailer: mh6.5
Date: Thu, 27 Aug 87 10:51:21 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry this note has dragged on so long, but the name to object mapping
is a difficult enough problem that I think it requires some thought.
THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
As my previous note outlined, the problem with making SYMBOL-FUNCTION
sensitive to the environment is that it directly conflicts with the
Common Lisp notion of the symbol's function cell as a global place.
On the other hand, the consequences for CLOS of not somehow making
the metaclass protocol for generic functions sensitive to the environment
are that support for resolving method inheritance at compile time
will not be available in a portable way (it may and probably will be
available in an implementation dependent way, since optimizations
will require it).
A good solution should somehow avoid either of these extremes. In
addition, the solution should not be such that compilation of a
method causes redefinition of anything funcallable in the compiler's
run time environment, since this could cause bootstrapping to fail.
This particular property rules out, for example, allowing the
symbol's function cell to become like a dynamically bound function
variable.
SOME POSSIBLE SOLUTIONS
The following are some possible solutions:
1) The symbol function cell could be eliminated as a global object and
the name to funcallable object mapping could be maintained within the
environment, as is the case in Scheme.
2) The generic function slot accessor functions could take an
environment argument and return information accordingly. This
was the solution I believe Patrick proposed.
3) We could simply leave it up to implementors to supply these
hooks, if they so choose.
Nice properties of each solution are:
1) The existence proof of Scheme and T shows that this solution can be
implemented. It also has a certain elegence.
2) No radical changes in existing Common Lisp implementations would be
needed.
3) No radical changes in the current spec for CLOS would be needed.
Nasty properties of each solution are:
1) Radical changes in existing Common Lisp compilers would be needed.
The issue of a single function/value cell is controversial, this could
be even more so.
2) This would complicate the metaclass protocol for generic functions
considerably. In particular, generic function slot accessors would need
to maintain data structures for mapping environments to methods, and
the dispatch function would need to do the "right" parameter specializer
to method function mapping, namely the one established when the method
was interpreted or loaded.
3) Implementation of object-oriented languages on the metaclass kernel
which resolve method inheritance at run time would have no support.
Optimizations of method lookup would be largely implementation dependent.
I don't like 2 is because it adds additional complexity to
the generic function protocol which I would rather avoid. I actually
like 1 best, but doubt we could ever get it implemented.
In the interests of wrapping up the loose ends of CLOS as expediently as
possible, I'd like to weigh in in favor of 3. While I think that the
metaclass kernel is an important part of CLOS, most people who want to
use it are more interested in the language for application implementation.
As I hope my previous posting has shown, the CLOS language (or programmer
interface) has no need for maintaining a seperate definition of generic
functions and methods in the compile time environment, since there is
no information about methods and generic functions previously compiled in a
file which needs to be portably transferred from form to form. In addition,
although the lack of this capability made implementation difficult,
the implementation of CommonObjects on the PCL kernel has shown that
a language which resolves most of method inheritance at compile time
can be done.
∂27-Aug-87 1656 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Solutions to Name/Object Mapping for Generic Functions
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Aug 87 16:55:33 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa09283; 27 Aug 87 19:42 EDT
Received: from ti-csl by RELAY.CS.NET id aa05932; 27 Aug 87 19:31 EDT
Received: from dsg by tilde id AA00730; Thu, 27 Aug 87 16:33:04 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Thu, 27 Aug 87 15:06:36 CDT
Message-Id: <2766081947-606167@Jenner>
Date: Thu, 27 Aug 87 15:05:47 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Solutions to Name/Object Mapping for Generic Functions
In-Reply-To: Msg of Thu, 27 Aug 87 10:51:21 MST from kempf%hplabsz@hplabs.hp.com
THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
The following are some possible solutions:
1) The symbol function cell could be eliminated as a global object and
the name to funcallable object mapping could be maintained within the
environment, as is the case in Scheme.
2) The generic function slot accessor functions could take an
environment argument and return information accordingly. This
was the solution I believe Patrick proposed.
3) We could simply leave it up to implementors to supply these
hooks, if they so choose.
If you are talking about name-to-generic-function mapping, 2 is not what
I have proposed. Name-to-generic-function mapping shouldn't depend on
the metaclass protocol since it should behave the same as
name-to-regular-function. Not being affected by the metaclass protocol,
it can be left to the implementation. The hook should be specified
though. If some implementations decide to ignore the environment,
that's fine. Since the environment is going to be passed explicitly(see
Moon's reponse to my proposal), we either need a new primitive for that,
or change SYMBOL-FUNCTION to accept an environment argument. A new
primitive for metaclass programmers is probably the best thing to do.
However I object to 3 since it will make serious metaclass programming
non portable.
Patrick.
∂27-Aug-87 1908 kempf%hplabsz@hplabs.HP.COM Re: Names to Objects and Compiler-environment
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 27 Aug 87 19:06:56 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Wed, 26 Aug 87 10:31:57 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Wed, 26 Aug 87 10:30:39 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Wed, 26 Aug 87 11:28:25 pdt
Message-Id: <8708261728.AA27357@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Names to Objects and Compiler-environment
In-Reply-To: Your message of Wed, 19 Aug 87 15:21:01 -0500.
<2765391661-13139657@Jenner>
Date: Wed, 26 Aug 87 11:28:22 MST
From: kempf%hplabsz@hplabs.HP.COM
THE PROBLEM
The fundamental problem I think we are trying to address with this
proposal is the transfer of information about class definitions
and potentially method definitions from form to form during a
file compilation. Such a transfer will necessary be implementation dependent,
but we would like to design an interface to the metaclass protocol which
is portable. The information on these definitions should
either not be a "real" definition or it should be a seperate and shadowing
definition from the definition in compiler's run time environment (if any).
The alternatives are to either replace the definition in the compiler's
run time environment, or to not propagate any information on class
and method definitions being compiled between forms. If we chose the
former solution (replacing the definition in the compiler's run
time environment) we face a bootstrapping problem, since a method
or class necessary for the compilation of a file may get redefined
while the file is being compiled, breaking the compiler (admittedly, this
may not occur very often, but, if it does, it could be very disabling).
The latter solution (not propagating any information) would place
an unreasonable burden on programmers using CLOS, since they would be
required to place class definitions and definitions of methods working
on those classes into seperate files. Usual practice in object-oriented
programming is to group class definitions and method definitions into
the same file, for easy reference.
THE PROPOSED SOLUTION
A solution has been proposed in which certain metaclass protocol
functions (generic and otherwise) take parameters which are "environments".
The exact nature of these environment parameters is unspecified, but
in order for them to be accessable to the top level macros DEFCLASS
and DEFMETHOD without adding alot of additional machinery to Common Lisp,
the most logical choice, as Moon has pointed out, is the macro &ENVIRONMENT
parameter.
The metaclass functions which Patrick has identified as being involved
in name to object mapping are:
CLASS-NAMED (aka SYMBOL-CLASS) - maps a symbol to a class
object having that name.
SYMBOL-FUNCTION - maps a symbol naming a (potentially generic)
function to the (potentially generic) function object.
GET-METHOD - ? according to pg. 2-39 of 87-002, this
takes a generic function object, list of method qualifiers,
and a list of parameter specializers (which, presumably,
are also objects) and produces the method.
Sonya has added:
GET-SETF-GENERIC-FUNCTION - maps a name for a generic
function into the generic function for doing the SETF.
I would argue that, of these, CLASS-NAMED and SYMBOL-FUNCTION are
at the right primitive level to discuss. My reasoning is as follows.
As the spec for GET-METHOD indicates, it is not doing a name to
object mapping but rather an object to object mapping. Thus
the more primitive operations CLASS-NAMED and SYMBOL-FUNCTION can
be used to find the objects, CLASS-NAMED to find the specializer
list, and SYMBOL-FUNCTION to find the generic function. As far
as GET-SETF-GENERIC-FUNCTION goes, it is doing a name to object
mapping, but the mapping is slightly bogus, since the name for a
SETF generic function is created, and the operation could just
as well be done by passing the generic function object for which the
SETF generic function was desired. The generic function object
might have to keep around information about it's SETF, however.
Alternatively, the algorithm for generating the SETF name could
be published (a user can find it simply enough anyway by
macroexpanding a SETF form) and we are back in the case where
SYMBOL-FUNCTION is the correct primitive for finding the
generic function.
Naturally, along with the functions for doing the name to object
mapping, the functions for doing a SETF will require an environment
argument as well. These would be the SETF functions for CLASS-NAMED
and for SYMBOL-FUNCTION.
Additional CLOS functions which Patrick has identified as possibly
requiring an environment argument are: ADD-METHOD, REMOVE-METHOD,
FIND-APPLICABLE-METHODS (presumably for use with CALL-NEXT-METHOD),
and ENSURE-GENERIC-FUNCTION. While these do not explicitly
do name to object mapping, I believe the logic here is the following:
ADD-METHOD, REMOVE-METHOD - addition and removal of a method from
a generic function is dependent on the environment, since a
different method definition may be desired on a generic function
in the compile time environment from what is available in the
compiler's run time environment (the "outside" or "top" environment).
FIND-APPLICABLE-METHODS - the compilation of a CALL-NEXT-METHOD
form will require access to methods as they are "defined" or,
at the very least, to the definitions compiled during a file
compilation, so the "current" definition is used for arranging
the method call, rather than the definition in the compiler's
run time environment.
ENSURE-GENERIC-FUNCTION-This does an implicit name to generic
function mapping, setting up any existing function (generic
also?) as a default method. Since it will probably use
SYMBOL-FUNCTION to retreive the function object bound to
the symbol's function cell, an environment parameter might
be needed to indicate which particular generic function
is required.
Of these, only ENSURE-GENERIC-FUNCTION takes a function name as an
an argument, the others all take generic function and other objects.
Hence, sensitivity to the processing environment need only be included
in ENSURE-GENERIC-FUNCTION, since only it will have to internally
resolve a name to object mapping.
One group of functions Patrick missed in his list is the metaclass
functions on pg. 3-25 of the metaobjec protocol specification.
They are all defined to take a name for the appropriate metaclass.
With the exception of DEFINE-METACLASS (which can be a macro anyway,
and thus use its &ENVIRONMENT parameter), the others could as well
be defined to operate on a class object which was a metaclass,
rather than directly on a metaclass name.
WHY CLASS DEFINITIONS NEED TO BE ENVIRONMENT SENSITIVE
I believe that an excellent case can be made for an environment argument
to CLASS-NAMED, and, correspondingly, that class definitions need to
be made both in the compile time environment (but *not* in the
compiler's run time environment) and at load time, as usual.
The arguments presented in the first section indicated why some way
of maintaining information on classes being defined needs to be propagated
between forms during a file compilation, independently of any definitions
in the compiler's run time environment.
An alternative for doing the definition "for real" is to maintain
information about definitions being compiled, then have the relevent
metaclass protocol functions distinguish whether the information about
a particular definition comes from the "for real" definition or from the
partial definition. I do not like this solution because it introduces
an additional element of complexity into the metaclass protocol which
somehow seems unnecessary, and sets up a more sharp distinction between
compiling a definition and evaluating it than simply switching
environments. CommonObjects did things this way, and it slowed down
compilation and made for some nasty case analysis. For example, handling
the distinction between the following two cases would be nontrivial
(in each case, the class FOO is also defined in the compiler's run time
environment):
Case 1:
(defclass foo () () )
(setf *global-var* (make-instance 'foo))
Case 2:
(defclass foo () () )
(eval-when (compile)
(setf *global-var* (make-instance 'foo)))
Though it could be disputed, I think the intent of Case 1 is to have
MAKE-INSTANCE use the FOO defined immediately above it, and that
the compiler, running in *not-compile-time-mode* (CLtL 69), should
defer instance creation and execution of the SETF until load time,
while, in the second case, instance creation and SETF should get done
at compile time using the definition in the compiler's run time
environment (*compile-time-too* mode) rather than the immediately
preceeding defintion, (except for KCL, which runs in *compile-time-too*
mode at the top level, but it is definitely in the minority).
If a compile time environment is used, then the EVAL-WHEN (COMPILE)
can simply be viewed as "popping" back to the compiler's run time
environment within the dynamic scope of the form, and returning to
the compile-time environment when the form ends.
The required behavior from DEFCLASS would be that the establishment
of a name to class object mapping is made via the &ENVIRONMENT
parameter, at compile time, and in the top level environment, at
load time. This suggests some way of obtaining the top level
environment for inserting the class name to object mapping.
Following Patrick's suggestion, a function GET-CURRENT-ENVIRONMENT
could be used. Another possibility is a special variable, *ENVIRONMENT*,
which would be bound to the current environment, similarly to how *PACKAGE*
is bound to the current package. I'd be interested in hearing if
this would have problems, as Moon's comments about GET-CURRENT-ENVIRONMENT
seem to indicate:
>If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
>some form of dynamic scoping, rather than lexical scoping, and you can
>get scoping problems. Symbolics' implementation, and I believe TI's as
>well, currently works this way, using the special variable
>SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
>environment they are working. The genesis of this is historical and
>predates lexical scoping. This causes a number of subtle problems.
>CLOS should not make this mistake.
though I'm not quite sure what sorts of arguments GET-CURRENT-ENVIRONMENT
should have or how this relates to dynamic scoping. The idea with
*ENVIRONMENT* is that it would be bound to the current macroexpansion
environment, which may or may not be EQL to the &ENVIRONMENT parameter
of a macro (*MACROEXPAND-HOOK* could be used to modify whether this is
true or not) but they would, in any event, be the same "kind" of environment.
Exactly how the name to object binding is inserted into the environment
would, of course, be implementation dependent (but this could be
hidden within CLASS-NAMED).
In addition, DEFCLASS would naturally have to use definitions within
the &ENVIRONMENT parameter for things like determining inheritance
information necessary at compile time. What kinds of information
would be necessary? For the moment, let's ignore optimization information,
since things get a bit more complicated when it is taken into account.
Given this, we can rule out slot layout and number information, since
WITH-SLOTS :USE-ACCESSORS NIL (the only place it would potentially be needed)
should go through SLOT-VALUE. Possibly the slot :INITFORM (and any
additional initialization information) would need to be compiled, but
they would not have to be accessed by anyone else. The only really
important piece of information needed would be the SETF generic
function names for inherited slots, since these would be required for
expanding SETF forms at compile time. Most other aspects of inheritance
(modulo optimizations) could be handled at load time or run time.
In order to make things more convenient for the user, we may want
to define an interface function called CLASS-NAMED, which takes the
class out of the current environment, and a metaclass function,
called SYMBOL-CLASS, which requires an environment argument.
Corresponding SETFs would also be required. But this seems as
if it should be the only modification needed for dealing with
the name to class mapping.
As a side note, I did an experimental implementation of something
similar using the CommonObjects on CommonLoops implementation this spring.
The part modifying CLASS-NAMED to be sensitive to the compilation
environment worked very well, which leads me to believe that implementation
should be possible.
WHY SYMBOL-FUNCTION DOESN'T NEED AN ENVIRONMENT PARAMETER
FOR THE DEFAULT CLOS LANGUAGE
The other part of the initial proposal involved shadowing generic
functions and methods in the compile time environment by making
the name to function mapping dependent on the environment.
The effect would be to require SYMBOL-FUNCTION to have an environment
parameter, since SYMBOL-FUNCTION and its SETF are the means whereby a
name to (possibly generic) function mapping is established.
Note that any attempt to make the name to function mapping dependent
on the environment will inevitably have some serious reprecussions
for Common Lisp. In particular, the design of Common Lisp assumes
functions are named by symbols in a global name space, partitioned
through packages. These symbols have a globally accessable function
cell, which SYMBOL-FUNCTION, FBOUNDP, MAKFUNBOUND, and other accessor
function access. Thus function names are kind of like special variables
except they can't be dynamically bound, or, more precisely, like global
variables in other languages (Pascal, for example), where dynamic
binding is not available. The name to function mappings established
by FLET and LABELS are not available via. SYMBOL-FUNCTION.
Referring back to the initial motivation for including environment
sensitivity, namely information propagated from form to form, there
is only one case where one method might need to know something about
another 's definition during compilation: CALL-NEXT-METHOD. However,
ignoring optimizations for the moment, the characterization of
CALL-NEXT-METHOD as lexical in scope and dynamic in extend suggests
lookup of the next method could be done, at the latest, at run time
exactly as method dispatch is done. Knowledge about the classes
of the caller's parameters at compile time could be used to limit
the run time method search. Various further optimizations are possible,
but the most obvious require only the ability to do method lookup
and linking at load time.
WHY SYMBOL-FUNCTION MAY REQUIRE ENVIRONMENT DEPENDENCY IN THE
METACLASS PROTOCOL
Unfortunately, some object oriented languages resolve method inheritance
fully at compile time. CommonObjects is an example. CommonObjects
has a form similar to CALL-NEXT-METHOD (called CALL-METHOD) which
allows the programmer to specify a particular method on the direct
super (or on itself), and a function call to the method (via. a
special method symbol) is compiled in at compile time. Thus the
CALL-METHOD macro must have access to the symbol at compile time,
and the fasl loader must maintain a compile time to load time
mapping of the symbol. This is all implementation dependent, of
course, and this particular feature has given us much trouble
in developing the Portable CommonObjects implementation. The
point is, however, that compiling a file of CommonObjects methods
requires information on the methods previously compiled to be
propagated between forms.
As mentioned in the previous section, addition of an environment
parameter to SYMBOL-FUNCTION (and its SETF) would involve a
major change to the semantics of function symbols in Common Lisp.
Since the function cell is a globally accessable place, would
redefining a function in a particular environment still cause
the global definition to change? If so, then bootstrapping problems
could easily occur, since a definition which has just been compiled
should not be used in the compilation process. If not, then the
nature of the function cell as a globally accessable place is
compromised, since function invocations in the compiler's run
time environment will get one definition, while another definition
will be operative in the compilation environment.
∂28-Aug-87 0150 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Aug 87 01:50:47 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217984; Fri 21-Aug-87 10:17:46 EDT
Date: Fri, 21 Aug 87 10:17 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Agenda for September meeting
To: kempf%hplabsz@hplabs.HP.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <8708202023.AA19448@hplabsz.hpl.hp.com>
Message-ID: <870821101706.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 14:23:16 MST
From: kempf%hplabsz@hplabs.HP.COM
With regard to the spec documentation, I'd like to put in a vote for an ASCII
version to go on parcvax, along with the portable source, so people don't
have to be working in the dark with it. The ASCII version doesn't
necessarily have to be up to the current level of discussion and
decision within the committee (indeed, it probably shouldn't) but should
reflect approximately what is implemented.
Please don't confuse the spec documentation with documentation for an
implementation. These are two very different things!
∂28-Aug-87 1912 Moon@STONY-BROOK.SCRC.Symbolics.COM Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Aug 87 19:12:23 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 223738; Fri 28-Aug-87 22:13:25 EDT
Date: Fri, 28 Aug 87 22:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870828221318.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Draft of a new object creation proposal based on CLOS subcommittee
discussions July 2, 1987.
-foo- means the word foo in italics. FOO means the word foo in boldface.
ONE NEW IDEA YOU HAVEN'T SEEN BEFORE
There is a new lambda-list-keyword, &METHOD-KEY, which is only valid in
DEFGENERIC-OPTIONS and DEFGENERIC-OPTIONS-SETF. The syntax of the lambda-list
in these macros becomes
({-var-}+
[&optional {-var-}*]
[&rest -var-]
{ [&key {-var- | ((-keyword- -var-))}* [&allow-other-keys]]
| [&method-key [&allow-other-keys]] })
The meaning of &METHOD-KEY is that the specific set of named arguments
accepted by the generic function varies depending on the positional arguments.
The named arguments accepted by the generic function for a particular call are
the union of the named arguments accepted by the applicable methods. There is
no attempt to exclude methods that are applicable but are not actually called.
Note that in standard method combination, all applicable methods are
potentially callable, if CALL-NEXT-METHOD is used. A method that has &REST,
but not &KEY, does not affect the set of acceptable named arguments. If the
lambda-list of any applicable method or of the DEFGENERIC-OPTIONS has
&ALLOW-OTHER-KEYS, all named arguments are accepted by the generic function.
The implementation of &METHOD-KEY is in two parts: The macro expansion of
DEFMETHOD, when the generic function uses &METHOD-KEY, is altered to save a
list of the acceptable named-argument names in a slot of the method object and
to put &ALLOW-OTHER-KEYS into the lambda-list of the function. If the
lambda-list already contains &ALLOW-OTHER-KEYS, then that symbol is stored in
place of the list of acceptable named-argument names (which would be
infinite). The function METHOD-NAMED-ARGUMENTS retrieves this list or symbol.
Secondly, the generic-function-to-method dispatching mechanism must check the
validity of the argument list when the generic function uses &METHOD-KEY and
does not use &ALLOW-OTHER-KEYS. This is accomplished by collecting the
acceptable named-argument names from the applicable methods and checking the
arguments against the union of those lists. If for any applicable method
METHOD-NAMED-ARGUMENTS returns &ALLOW-OTHER-KEYS, the whole check is skipped.
CONCEPTS TO BE ADDED TO 87-002
-named argument-. We use the term "named argument" instead of "keyword
argument" (as in CLtL) for &key arguments, because CL-Cleanup issue
KEYWORD-ARGUMENT-NAME-PACKAGE has stated that the names of &key arguments
do not have to be keyword symbols.
-named argument name-. The symbol that identifies a named argument in
an argument list. This is typically a keyword, but is not required to be.
The named-argument name should not be confused with the variable name
of the parameter variable. These two symbols typically have the same
name and are typically in different packages, but that is not required.
-initarg-. An initarg (initialization argument) is a named argument that
can be used to control object creation and initialization. The &key
arguments to MAKE-INSTANCE are initargs. Each initarg has a name, which is
a symbol, and may have a value, which is any Lisp object. It is often
convenient to use keyword symbols to name initargs, but the name of an
initarg can be any symbol, including NIL.
-initarg list-. An initarg list (initialization argument list) is a list
of alternating initarg names and values. Its structure is identical to a
property list and also identical to an &key argument list. As in those
lists, if an initarg name appears more than once in an initarg list, the
leftmost occurrence supplies the value and the remaining occurrences are
ignored. The arguments to MAKE-INSTANCE, after the first, are an initarg
list. As in an &key argument list, :ALLOW-OTHER-KEYS can appear in an
initarg list, and if its value is non-NIL, error-checking of initarg names
is disabled.
-slot-filling initarg-. An initarg associated with a slot. If the initarg
has a value, the value is stored into the slot of the newly-created object,
overriding any initform associated with the slot. -(What about shared
slots?)- A single initarg can fill more than one slot.
-method-implemented initarg-. An initarg associated with a method. When
an object is created, the method is called with the initarg's value as an
argument and the method uses the value in any way it likes. If the initarg
has no value, the method's lambda-list supplies a default value. A single
initarg can be implemented by more than one method. An initarg can be both
slot-filling and method-implemented.
CHANGES TO 87-002 FEATURES
DEFCLASS gets a new :INITARG slot option, which is followed by a symbol.
The symbol becomes the name of a slot-filling initarg for this class.
DEFCLASS gets a new :DEFAULT-INITARGS option, which is followed by an initarg
list. Each value in this list is a form that is evaluated by MAKE-INSTANCE if
the initarg does not already have a value. The forms are evaluated in the
lexical environment in which the DEFCLASS form was evaluated.
Method-implemented initargs are defined simply by defining a method for
INITIALIZE-INSTANCE or ALLOCATE-INSTANCE; each named-argument name in the
method's lambda-list becomes a method-implemented initarg for all classes for
which this method is applicable.
Initarg inheritance: The effective set of slot-filling initargs for a class C
is the union of the slot-filling initargs defined by C and its superclasses.
The effective set of method-implemented initargs for a class C is determined
by method inheritance.
Default-initargs inheritance: [same as for the :INITFORM slot option]
Changes to Lambda-list Congruence Rules (p.1-20): Rules 1, 2, and 6 remain
the same, except for wording problems, while rules 3-5 need to be replaced
to implement &METHOD-KEY and to fix the interaction among &KEY, &REST, and
&ALLOW-OTHER-KEYS. The new rules for congruence are the following:
These rules define the congruence of a set of lambda-lists, including the
lambda-list of each method for a given generic function and the lambda-list
specified with DEFGENERIC-OPTIONS, if present. For -SETF methods, these
rules apply to the effective lambda-list produced by combining the two
specified lambda-lists according to the rules on page nnn.
1. Each lambda-list must have the same number of required parameters.
2. Each lambda-list must have the same number of optional parameters.
Each method can supply a different default for an optional parameter.
3. If any lambda-list uses &REST, &KEY, or &METHOD-KEY, each lambda-list
must use one or more of these. Note that &METHOD-KEY is only valid in
DEFGENERIC-OPTIONS.
4. If the DEFGENERIC-OPTIONS does not use &METHOD-KEY, or there is no
DEFGENERIC-OPTIONS, each method that uses &KEY and does not use
&ALLOW-OTHER-KEYS must specify the same named-argument names.
5. The use of &ALLOW-OTHER-KEYS need not be consistent across lambda-lists.
6. The use of &AUX need not be consistent across methods.
Rules when initargs are duplicated:
The :INITARG slot-option may be specified more than once for a given slot.
A single initarg can initialize more than one slot if the same initarg name
appears in more than one :INITARG slot-option.
If two initargs that initialize the same slot, with the same or different
names, are given in the arguments to MAKE-INSTANCE, the leftmost of these
initargs in the initarg list prevails.
If two different initargs that initialize the same slot have default values,
the initarg that appears in a :INITARG slot-option in the most specific
class prevails, or if they appeared in the same class, the one leftmost in
the slot-options list prevails.
It is valid for a given initarg name to be defined more than once as a
slot-filling initarg, as a method-implemented initarg, or both.
NEW FUNCTIONS TO BE ADDED
In this section, I have only sketched each function, for the sake of brevity.
Full writeups can be constructed once the overall framework has been agreed
upon. Functions are in alphabetical order. By coincidence, all functions
listed are generic and expected to specialize on their first argument.
(ALLOCATE-INSTANCE class &method-key &allow-other-keys) => instance
Metausers can replace the system-supplied, implementation-dependent
method for this.
(CHECK-INITARGS class initarg-list)
Metausers could replace the system-supplied method that implements the
normal rules for initarg validity.
(CLASS-ALL-INITARGS class) => list of initarg names (includes inherited)
(CLASS-DIRECT-INITARGS class) => list of initarg names
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
(CLASS-DIRECT-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
(CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods
(DEFAULT-INITARGS class initarg-list) => initarg-list
The system-supplied method implements the :DEFAULT-INITARGS class option.
[This could specialize on instance instead of class, but I don't
see any point to that.]
(ENCACHE-INITARG-INHERITANCE class)
This is called by the system at least once before a class is instantiated,
and is called again whenever anything relevant changes. System-supplied
methods for this conspire with methods for CHECK-INITARGS, etc., to make
MAKE-INSTANCE faster. Users with their own caching needs can add methods
for this generic function.
(ENCACHE-METHOD-INHERITANCE class)
(ENCACHE-SLOT-INHERITANCE class)
(INITIALIZE-INSTANCE instance &method-key &allow-other-keys)
Users define :AFTER methods for this to create method-implemented initargs.
The primary method for this is system-supplied and takes care of the
slot-filling initargs.
(MAKE-INSTANCE class &key -initargs-...) => instance
(METHOD-NAMED-ARGUMENTS method) => list of symbols or &ALLOW-OTHER-KEYS
(SLOT-BOUNDP instance slot-name) => boolean
Allows writing INITIALIZE-INSTANCE methods that only initialize slots if they
haven't been initialized already.
(SLOT-MAKUNBOUND instance slot-name) => NIL
PROCEDURAL DEFINITION OF MAKE-INSTANCE
MAKE-INSTANCE behaves as if it was defined as follows, except that certain
optimizations are permitted, as detailed below.
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
Optimization is possible, including inlining and constant-folding of method
lookup and method bodies, provided that the programming environment either
prohibits redefining these methods or updates everything when they are
redefined. A possible example implementation would be that MAKE-INSTANCE has
a separate method for every class, which is automatically written and compiled
by the system.
This optimization relies on the ENCACHE-INITARG-INHERITANCE generic function
and some unpublished slots of STANDARD-CLASS.
Because of optimization, methods for the generic functions listed may not
actually be called on every call to MAKE-INSTANCE, or may not receive
exactly the arguments that would be expected. For example, CHECK-INITARGS
may actually be called before DEFAULT-INITARGS rather than after, if it has
already been determined that the default initargs will pass CHECK-INITARGS.
Additional explicit details of permissible optimization will need to be set
forth.
MEETING OF STATED DESIGN GOALS
Lexical proximity of concepts--the declaration of an initarg as valid,
the specification of what it does, and the default if it is not supplied
are all together, in a slot specifier or in a method lambda-list.
Simple ways to do simple things--slot-filling initargs don't require the
user to write any code. Method-implemented initargs work just like
ordinary function arguments as far as the user is concerned.
Minimal number of new languages--the only addition to Common Lisp is
&METHOD-KEY.
Ability to do everything at some level--the underlying procedural level
is available. Functions to access all the direct and inherited
information are documented.
Underlying mechanism is exposed so user can use it for other things,
rather than abusing instance creation as the only way to access the
mechanism--the combination of &method-key, method-named-arguments,
compute-applicable-methods, and encache-initarg-inheritance provides
everything the user needs.
∂30-Aug-87 1946 RPG Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
On July 27 Kempf mailed a note about the description of the class
precedence list algorithm. Because I was away until yesterday, I
was not able to respond:
Kempf writes:
1) The use of the term "partial order" on pg. 1-15, paragraph 1
implies a relation on R which is reflexive, antisymmetric, and
transitive. From the text of the paragraph, this relation is
presumably the "is a subclass of" relation. However, earlier in
the document, reflexivity is explicitly excluded from the "is a
subclass of" relation (pg. 1-4, paragraph 3), since a class is
defined to be neither a superclass nor a subclass of itself.
Either the partial order needs to be replaced with a different
order not requiring reflexivity (semiorder, etc.) or the "is a
subclass of" relation needs to be redefined so that it is
reflexive. Note that the latter solution is used in more
technical treatments of typing systems (e.g. Cardelli and
Wegner, Computing Surveys, 17, 1985, pp. 471-522).
Knuth points out that one can define partial orderings using ``less than
or equal'' and so does not require the antisymmetric condition. We should
be more explicit here about it and define the partial ordering on a true
reflexive, antisymmetric, and transitive relation.
Kempf writes:
4) The formal description of class precedence list calculation
on pg. 1-15, paragraph 3 is lacking a condition. In the third
line, it is not sufficient just to require the existence of an
index i, but also its minimality. As a counterexample,
consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4 c6)} The
inheritance graph for this is....
Well, this is the result of a misreading of the algorithm. However,
this is sufficient to require a rewrite of the description. As an aside
to JAK, let me point out the following: his example was:
c5 c6
| |
c3 c4
| |
\ /
\ /
c2
|
c1
The relations used to define the partial ordering are:
{(c1 c2)(c2 c3)(c2 c4)(c3 c4)(c3 c5)(c4 c6)}
The key one is that c3 precedes c4.
When the CPL is [c1 c2], there is only one class with no predecessors -
C3.
I believe the description of the algorithm to be correct, but I stand accused of
and confess to it being a difficult description. I will volunteer to try to fix
it up.
By the way, have we thought about various means of making the CPL more
accessible, such as what New Flavors does?
∂30-Aug-87 2009 RPG Miscellaneous decisions taken or to be taken
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
The document says ``the binding for the local variable CALL-NEXT-METHOD
has lexical scope and dynamic extent.''
The idea is that a user would not even be allowed to create a closure
that refered to CALL-NEXT-METHOD. I suppose he could, but he'd get some
global defintion for CALL-NEXT-METHOD. We intend to not provide a poor man's
continuation mechanism. I didn't think we even had anything as sophisticated
as hierarchy redefinition in mind when we wrote this. The description needs to
be clearer.
-rpg-
∂30-Aug-87 2017 RPG Agenda
To: common-lisp-object-system@SAIL.STANFORD.EDU
The agenda seems fine to me. The key to making the meeting work is for
people to dedicate time to studying the proposals and doing what they
have volunteered to do. I, for example, will get to work on the
anonymous generic function progosal tomorrow, and you will all have it
within a week.
Because I just returned from Europe, I don't even know what arrangements
Linda has made. But, again, there is no territorialness in what they are,
it is a matter of someone volunteering to do the work and then doing it.
Danny was also in Europe, and no one else had stepped forward.
On the document: I earlier promised to produce a minimal TEX macro file
so that people could roll their own. It was a lack of time on my part that
prevented that rather than some sinister plot. I hope I can get that done in
a day and put it out on SAIL along with the TEX sources. The problem with the
current macro file is that it is many dozens of pages long and contains the
book layout definition for all of Lucid's manuals.
-rpg-
∂30-Aug-87 2024 RPG Name That Class!
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Before I left on my ill-fated trip to Europe (where I confronted face-to-face,
once more, my muse) I wrote out some examples of how class objects and their
names interacted. The idea was to explore what it meant to build a hierarchy
with names (using DEFLCASS) and with class objects (blasting fields). I think
these examples are right (I could be wrong) and they might strike some as
odd, they are generally in accord with acceptable behavior of functions and
the symbols that name them (and DEFSTRUCT names and types as well). I send them
in hopes they might help stimulate thought on the issues:
1. (defclass foo ...)
(let ((a (class-named 'foo)))
(defclass foo ...)
(eq a (class-named 'foo))) => T
This has been agreed to be the best sufficient way to achieve the
old-methods-still-work behavior.
2. (defclass foo ...)
(let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c)
(eq (class-named 'foo) c)) => ?
MAKE-INSTANCE is not psychic, so it must cons. It seems that (DEFLCASS FOO ...)
is equivalent to
(let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c)
c)
Note that there is no similar expression in CLtL to which DEFTSRUCT is
equivalent. Therefore the EQ must return NIL. This implies that (setf
(class-named ...) ...) is smart and worries about the EQness between the
previous class, if it exists, and the new one.
3. (let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c) ;foo otherwise undefined
(eq (class-named 'foo) c)) => ?
Why should (setf (class-named ...) ...) unnecessarily cons? Therefore
the EQ should return T.
4. (defclass foo ...)
(defclass baz ...)
(let ((c1 (class-named 'foo))
(c2 (class-named 'baz)))
(setf (class-named 'baz) (class-named 'foo))
;;; (eq c1 c2) => NIL
(eq (class-named 'foo) (class-named 'baz))) => ?
Because (eq c1 (class-named 'foo)) => T, (eq c1 c2) => NIL, and (eq c2
(class-named 'baz)) => T, this must return NIL.
5. (defclass foo ...)
(defmethod f ((x foo)) ...) ;no other methods
(defclass baz ...)
(defmethod g ((x baz)) ...) ;no other methods
(setq instance1 (make-instance 'foo))
(setq instance2 (make-instance 'baz))
(rotatef (class-named 'foo) (class-named 'baz))
(f instance1) => well-defined?
(f instance2) => well-defined?
(g instance1) => well-defined?
(g instance2) => well-defined?
The first generic function invocation is well-defined; the second is an
error of some sort; the third is an error of some sort; the fourth is
well-defined.
6. (defclass c1 (c2 c3) ...)
(defclass c2 ...)
(defclass c3 ...)
(defmethod f ((x c2)) ...) ;no other methods
(setq instance1 (make-instance 'c1))
;;; Flush the superclass link from C1 to C2
(setf (class-super-classes (class-named 'c1)) `(,(class-named 'c3)))
(f instance1) => well-defined?
I don't know what this should do, but I suspect the expression (f instance1)
is not well-defined because the SETF alters the topology of the graph.
It seems that once a name is given to a class, the symbol that is the
name and the storage for that class are linked forever unless something
like
(setf (class-named 'foo) nil)
is defined to work.
It is also clear that the the applicability of methods within a class
graph depends on the topology of the graph and not on the substance of the
classes in that graph. If a user were to mistakenly exchange the names of
two classes in a graph at the outset, he would not be able to correct that
naming error using CLASS-NAMED and (SETF (CLASS-NAMED ...) ...) - example
4 shows this. He would have to alter the superclass slots in the classes
surrounding the ones he wishes to switch, according to the technique in
example 6, assuming that would even work.
Enjoy!
-rpg-
∂30-Aug-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Aug 87 20:53:31 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 224284; Sun 30-Aug-87 23:54:35 EDT
Date: Sun, 30 Aug 87 23:54 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Aug 87 22:46 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870830235432.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Aug 87 1946 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
By the way, have we thought about various means of making the CPL more
accessible, such as what New Flavors does?
Yes, I signed up to write a proposal that would try to satisfy Gregor's
objections to the proposal I presented previously, as best as I could
understand them. I haven't done it yet, though. I've been putting my
time into make-instance instead.
∂31-Aug-87 0802 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Aug 87 08:02:20 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 31 Aug 87 08:00:47 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 31 Aug 87 08:00:25 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 31 Aug 87 09:01:03 pdt
Message-Id: <8708311501.AA16453@hplabsz.hpl.hp.com>
To: "Sonya E. Keene" <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Agenda for September meeting
In-Reply-To: Your message of Fri, 21 Aug 87 10:17:00 -0400.
<870821101706.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Mon, 31 Aug 87 09:01:00 MST
From: kempf%hplabsz@hplabs.HP.COM
> Date: Thu, 20 Aug 87 14:23:16 MST
> From: kempf%hplabsz@hplabs.HP.COM
> With regard to the spec documentation> , I'd like to put in a vote for an ASCII
> version to go on parcvax, along with the portable source, so people don't
> have to be working in the dark with it. The ASCII version doesn't
> necessarily have to be up to the current level of discussion and
> decision within the committee (indeed, it probably shouldn't) but should
> reflect approximately what is implemented.
> Please don't confuse the spec documentation with documentation for an
> implementation. These are two very different things!
I hope I'm not. My concern is that, if the process of finalizing the spec
and the portable implementation continue in tandem, as seems to be happening,
people will want to have a more accessable copy of the spec. Of course,
there will be differences between the spec and the implementation, and
these should probably be documented. Additionally, should a decision be made
not to pursue the portable implementation (which would be tragic, in my
opinion) then there would be little need. There are lots of people using the
current PCL/half CLOS at universities and such, and I think they'd like to
have a copy.
But I most whole-heartedly agree that the spec and any particular
implementation of it are seperate.
∂31-Aug-87 1914 MLY@AI.AI.MIT.EDU RPG's recent typo.
Received: from AI.AI.MIT.EDU by SAIL.STANFORD.EDU with TCP; 31 Aug 87 19:14:25 PDT
Date: Mon, 31 Aug 87 22:18:06 EDT
From: Richard Mlynarik <MLY@AI.AI.MIT.EDU>
Subject: RPG's recent typo.
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <248781.870831.MLY@AI.AI.MIT.EDU>
Perhaps DEFCLASS could be renamed DEFTSTRUCT.
∂01-Sep-87 1150 Gregor.pa@Xerox.COM Re: Name That Class!
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Sep 87 11:49:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 SEP 87 10:11:53 PDT
Date: 1 Sep 87 10:11 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Name That Class!
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 30 Aug 87
20:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870901-101153-7058@Xerox>
Your first example is right. But there is a mistaken assumption in your
second example that throws all the others off. Specifically, you say
that:
It seems that (DEFLCASS FOO ...)
is equivalent to
(let ((c (make-instance 'standard-class))) (setf
(<various aspects> c) <certain values>) (setf (class-named
'foo) c) c)
But this isn't right. (defclass foo ...) is equivalent to:
(let* ((existing (class-named 'foo t))
(new (if existing
(class-for-redefinition existing)
(make-instance 'standard-class))))
(setf (class-named 'foo) new)
(update-class new ..)
new)
Given this clarification, its clear that (for instances of
standard-class) the rest of your examples should return:
2. T
3. T
4. T
The point is that class-named has no smarts (remember that as much as
possible we don't want to do things that just couldn't map into a
Lisp-1, and certainly set! has no smarts). class-for-redefinition is
where all the smarts is.
∂01-Sep-87 1258 RPG Name That Class!
To: common-lisp-object-system@SAIL.STANFORD.EDU
It would be nice if it turned out that the relationship between
a class and its name could be as clean as the relationship between
a symbol and its value, but this is not the case: We can already
ask of a class its name.
When I wrote these examples I thought of two parallel activities going
on in two CLOS's right next to each other - one in which a user was using
DEFCLASS to build up a hierarchy and one in which a user was using
anonymous classes to build up the same hierarchy. My assumption about the
equivalence of DEFCLASS and the LET-expression was derived from a belief
that simplicity of model was desirable.
I don't, now, believe that the behaviors I listed in my message are alarming
(though I did originally) because one can imagine a Common Lisp in which
(defun f (...)...)
and
(setf (symbol-function 'f) (function (lambda (...)...)))
are equivalent and similar behaviors hold to the ones in that message (that
is, SETF of SYMBOL-FUNCTION is smart).
We also run into the problem that Common Lisp already treats types as a
sort-of subclass of SYMBOL, and so the tight name-to-object mapping
described in my message is not altogether out of line with an attempt to
integrate classes with types.
We haven't really talked about what DEFCLASS is equivalent to yet,
so I suppose there are now two proposals as to what that might be on
the table.
-rpg-
∂01-Sep-87 1300 RPG Anonymous Generic Function Proposal (Draft 1)
To: common-lisp-object-system@SAIL.STANFORD.EDU
There are 3 cases to consider:
1. Purely anonymous generic functions, corresponding to
(function (lambda ...)) in Common Lisp.
2. A set of named generic functions to be used within a particular
body, corresponding to (labels ...) in Common Lisp. An analog
to FLET might be appropriate also.
3. A means of extending a generic function currently defined on a
symbol (name). This corresponds to nothing in Common Lisp.
Here is a proposal, inspired by Guy Steele, which covers case 1:
(generic (lambda ...)
(lambda ...)
(lambda ...)
...))
This special form produces a generic function with the lambda-expressions
as the methods. This is about as similar to the FUNCTION syntax as can
be rationally gotten.
To cover case 2 we define an analog to Common Lisp LABELS, but instead of
functions the user defines methods:
(generic-labels ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
At this point it is easy to extend FLET similarly:
(generic-flet ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
The simplest means of producing an anonymous recursive generic function is:
(generic-labels ((self (...)...(self...)...)
(self (...)...(self...)...)
...)
#'self)
Notice that the special form FUNCTION will need to be amended in CLtL to
be able to produce a generic function, but this should be a natural fallout
of making a generic function a subtype of FUNCTION.
Handling case 3 is more difficult, because there is no corresponding
Common Lisp form to do a similar thing for functions. A danger is to
inadvertently design a form that will also accomplish the dynamic binding
of a function associated with a symbol.
(with-added-methods ((print (...)...)
(print (...)...)
(read (...)...)
(read (...)...)
(read (...)...))
<body>)
Among the things that could have been included in this proposal is
the ability to have the method functions be able to call each other
without going through the generic function object. However, this obscure
case can be hacked together using add-method etc, and I don't believe
it deserves a special syntax. (It might be so obscure you cannot understand
this description, but that only reinforces my argument.)
-rpg-
∂01-Sep-87 1823 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 1)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Sep 87 18:23:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 SEP 87 18:19:05 PDT
Date: 1 Sep 87 18:18 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 1)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
13:00 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870901-181905-7824@Xerox>
(with-added-methods ((print (...)...)
(print (...)...)
(read (...)...)
(read (...)...)
(read (...)...))
<body>)
Is this strictly lexical (only calls within the <body> have the added
methods), or is it dynamic (calls from any called function see the
methods, but the methods are removed when the fom is exited). Both are
useful I think.
danny
∂01-Sep-87 2317 RPG Anonymous Generic Function Proposal (Draft 2)
To: common-lisp-object-system@SAIL.STANFORD.EDU
Draft 1 is amended to take into account Danny's comment.
There are 3 cases to consider:
1. Purely anonymous generic functions, corresponding to
(function (lambda ...)) in Common Lisp.
2. A set of named generic functions to be used within a particular
body, corresponding to (labels ...) in Common Lisp. An analog
to FLET might be appropriate also.
3. A means of extending a generic function currently defined on a
symbol (name) or lexically. This corresponds to nothing in
Common Lisp.
Here is a proposal, inspired by Guy Steele, which covers case 1:
(generic (lambda ...)
(lambda ...)
(lambda ...)
...))
This special form produces a generic function with the lambda-expressions
as the methods. This is about as similar to the FUNCTION syntax as can
be rationally gotten.
To cover case 2 we define an analog to Common Lisp LABELS, but instead of
functions the user defines methods:
(generic-labels ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
This form produces 2 new generic functions, FOO and BAR.
At this point it is easy to extend FLET similarly:
(generic-flet ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
The simplest means of producing an anonymous recursive generic function is:
(generic-labels ((self (...)...(self...)...)
(self (...)...(self...)...)
...)
#'self)
Both GENERIC-LABELS and GENERIC-FLET produce new generic functions. The
fact that a generic function is already bound to a variable of the same
name or to a symbol is irrelevant to the operation of these forms.
Notice that the special form FUNCTION will need to be amended in CLtL to
be able to produce a generic function, but this should be a natural fallout
of making a generic function a subtype of FUNCTION.
Handling case 3 is more difficult, because there is no corresponding
Common Lisp form to do a similar thing for functions. A danger is to
inadvertently design a form that will also accomplish the dynamic binding
of a function associated with a symbol.
(with-added-methods <generic-function> (<methods>*) . <body>)
This takes a generic function and a list of methods specified as
lambda-expressions, extends the generic function by adding the appropriate
methods, and then executes the forms in <body> as if they were in a PROGN.
When WITH-ADDED-METHODS exits, the added methods are removed. Any flow of
control out of the WITH-ADDED-METHODS causes the methods to be removed.
Notice that this handles both anonymous and named generic functions.
For example:
(generic-flet ((foo (...)...) (foo (...)...))
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
(with-added-methods #'foo ((lambda (...)...)) <body>)))
-rpg-
∂02-Sep-87 1149 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Sep 87 11:49:10 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 SEP 87 11:49:27 PDT
Date: 2 Sep 87 11:49 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
23:17 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870902-114927-8581@Xerox>
When WITH-ADDED-METHODS exits, the added methods are removed.
Any flow of control out of the WITH-ADDED-METHODS causes the
methods to be removed.
I still find this ambiguous.
Consider
(defmethod fie (x) 0)
(defun foo (x)
(with-added-methods fie ((lambda ((x P1)) 17))
(cons (fie x) (fum x)))
(defun fum (y) (fie y))
(foo (make-instance 'P1))
==> (17 . 17)
or
==> (17 . 0)
∂02-Sep-87 1224 Pavel.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Sep 87 12:24:04 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 02 SEP 87 12:10:50 PDT
Date: Wed, 2 Sep 87 12:10:46 PDT
From: Pavel.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: <870902-114927-8581@Xerox>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870902-121050-8628@Xerox>
Another question about the proposal: What is the intent with respect to
multi-process environments? During the time that WITH-ADDED-METHODS is
active, should the other processes see the added methhods or not? I
would hope not;; this should have the same sort of behaviour as special
variables.
Pavel
∂02-Sep-87 1534 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Another try on object creation
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 2 Sep 87 15:34:34 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab03266; 2 Sep 87 17:59 EDT
Received: from ti-csl by RELAY.CS.NET id af13392; 2 Sep 87 17:48 EDT
Received: from Jenner by tilde id AA19802; Wed, 2 Sep 87 16:39:20 CDT
Message-Id: <2766605837-15560752@Jenner>
Date: Wed, 2 Sep 87 16:37:17 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Another try on object creation
In-Reply-To: Msg of Fri, 28 Aug 87 22:13 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
I have a question: Why don't you use a class prototype to call
default-initargs and check-initargs?
Patrick.
∂02-Sep-87 2013 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Sep 87 20:13:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 226977; Wed 2-Sep-87 23:13:58 EDT
Date: Wed, 2 Sep 87 23:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2766605837-15560752@Jenner>
Message-ID: <870902231340.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 2 Sep 87 16:37:17 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
I have a question: Why don't you use a class prototype to call
default-initargs and check-initargs?
That's the way the notes from the meeting had it, but in my proposal
I changed that for two reasons. One is that this was the only use
of prototypes, so by changing this we can eliminate the need to expose
that concept; it makes the standard simpler. The second reason is
a little more complex: in trying to figure out why there was such
apparent randomness, with some functions generic on the instance and
others generic on the class, I decided it must be that functions generic
on the instance can have methods defined by ordinary users, and can
have those methods combined with inheritance, while functions generic
on the class are part of the metaclass protocol and you only write
methods for them if you are doing over part of the implementation.
At the meeting we said that it was "hard to make default-initargs
and check-initargs generic" and left it at that. If you think about
check-initargs, all the checking has to be in one place; there is
no way to do it by combining inherited methods, each of which checks
one class's initargs. In fact there is one method for check-initargs
which looks at the slot-initargs and the lambda-lists of the applicable
methods and decides what to do. Therefore, I decided check-initargs
must be a metaclass method. The alternative would have been to have
a check-initarg generic function that checks one argument at a time,
which seemed unduly complex.
Less clear is defaulting, but what decided me there was that at the
meeting there was a move to combine default-initargs and check-initargs
into a single operation, in which case they would have to be generic on
the same thing. I don't really see much usefulness in users defining
their own default-initargs methods, when they are not working at the
metaclass level, so to keep things simple I made that generic on the
class.
It's true that in this formulation you can't do certain customized
defaulting and checking operations except by programming at the
metaclass level. However, making those two functions generic on the
instance still wouldn't make those operations simple and easy to explain
(see mail discussion of the past few months), and I think at some point
we have to limit the ambitions of CLOS and say that it doesn't replace
all forms of programming.
That's why I proposed it the way I did. This is not to say that no one
should propose that it work a different way, if they can refute the
arguments above. For this purpose, default-initargs and check-initargs
should be discussed separately.
∂03-Sep-87 1414 Bobrow.pa@Xerox.COM Re: Another try on object creation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Sep 87 14:14:21 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 SEP 87 14:14:38 PDT
Date: 3 Sep 87 14:14 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Another try on object creation
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 2 Sep 87 23:13 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870903-141438-10242@Xerox>
Patrick Asked
Why don't you use a class prototype to call
default-initargs and check-initargs?
Moon had two arguments for this
One is that this was the only use of prototypes,
so by changing this we can eliminate the
need to expose that concept; it makes the standard simpler.
The concept of class-prototype must be introduced for other reasons in
the metaobject protocol, so I don't buy this reason.
The second reason is ... functions generic on the class are
part of the metaclass protocol and you only write methods for them
if you are doing over part of the implementation.
My intuition (expressed in our initial propposal) was that
default-initargs, check-initargs etc were really user (instance)
business. However, I now agree with Moon that these mechanisms for
initialization (except for user-defined :after methods) are more closely
associated with the implementation of a class and hence are metaclass
methods. Ordinary users would rarely want to change them -- especially
if these methods are not guaranteed to be called each time (i.e.
optimized away) except at some great cost. Since I think these
optimizations are important in the standard case, I am happy to leave
default-initargs and check-initargs specialized on the metaclass.
I do have another question on the initialization proposal though. Why
do we need &method-key? Why not make the congruence rules for generic
functions be those Moon described for &method-key i.e. the acceptable
named arguments for a generic function are the union of the named
arguments of the methods, or &allow-other-keys. The one feature this
eliminates is the ability to define a generic function for which all
methods must have exactly the same named arguments. This seems a small
loss, and we gain by not having to add another lambda-keyword.
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
∂03-Sep-87 1705 kempf%hplabsz@hplabs.HP.COM Re: Solutions to Name/Object Mapping for Generic Functions
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 3 Sep 87 17:04:47 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 1 Sep 87 16:00:08 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 1 Sep 87 15:59:35 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 1 Sep 87 17:00:18 pdt
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Solutions to Name/Object Mapping for Generic Functions
In-Reply-To: Your message of Thu, 27 Aug 87 15:05:47 -0500.
<2766081947-606167@Jenner>
Date: Tue, 01 Sep 87 17:00:15 MST
Message-Id: <3994.557535615@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
> THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
>
>
> The following are some possible solutions:
>
> 1) The symbol function cell could be eliminated as a global object and
> the name to funcallable object mapping could be maintained within the
> environment, as is the case in Scheme.
>
> 2) The generic function slot accessor functions could take an
> environment argument and return information accordingly. This
> was the solution I believe Patrick proposed.
> 3) We could simply leave it up to implementors to supply these
> hooks, if they so choose.
> If you are talking about name-to-generic-function mapping, 2 is not what
> I have proposed.
Yes, you are right. What I should have said is that it is *similar* to
what you proposed. The original proposal mentioned modifying ADD-METHOD,
GET-METHOD, REMOVE-METHOD, FIND-APPLICABLE-METHODS, and
ENSURE-GENERIC-FUNCTION to take environment arguments, which are all part
of the metaclass protocol, in addition to SYMBOL-FUNCTION:
> 2- CLOS functions that must have an environment argument:
>
> CLASS-NAMED and its SETF form,
> ADD-METHOD,
> GET-METHOD,
> REMOVE-METHOD,
> FIND-APPLICABLE-METHODS,
> ENSURE-GENERIC-FUNCTION.
I believe the intention was, however, that they should pass the
environment on to SYMBOL-FUNCTION or use it in some implementation
dependent manner.
What 2 is proposing is to decouple modification of SYMBOL-FUNCTION to
take an environment parameter, which I believe will have serious
reprecussions for Common Lisp semantics, from the metaclass protocol
modifications. Modification of SYMBOL-FUNCTION would be the essense of
1.
> Name-to-generic-function mapping shouldn't depend on
> the metaclass protocol since it should behave the same as
> name-to-regular-function.
If SYMBOL-FUNCTION is modified to take an environment argument, then
the name-to-regular-function mapping is going to change too. A
metacircular definition of the Common Lisp interpreter might look like;
(cond
<other things>
( (fboundp (first form))
(apply (symbol-function (first form)) argument-list)
)
<more other things>
)
Changing SYMBOL-FUNCTION means this becomes;
(cond
<other things>
( (fboundp (first form))
(apply (symbol-function (first form) <environment>) argument-list)
)
<more other things>
)
But what environment? The current one? The base one? Modification of
SYMBOL-FUNCTION means that semantics of function application in Common
Lisp must be changed, becoming more like Scheme. Now, I have no objection
to this (in fact, I think it would be an improvement) but some compiler
writers and application developers might. Note that this semantic change
is very different from the one generic functions introduce, because it
involves global (environment) rather than local (parameter classes)
information, and hence could require larger modifications to existing
code.
> Not being affected by the metaclass protocol,
> it can be left to the implementation. The hook should be specified
> though. If some implementations decide to ignore the environment,
> that's fine. Since the environment is going to be passed explicitly (see
> Moon's reponse to my proposal), we either need a new primitive for that,
> or change SYMBOL-FUNCTION to accept an environment argument. A new
> primitive for metaclass programmers is probably the best thing to do.
I'm not quite sure what the "or" is here. I understand the proposal for
primitives to access the environment, but I don't understand where
the hook could be, other than through the metaclass method lambda lists.
A way to work around this difficulty might be the following. Instead of
modifying the name to generic function mapping to be sensitive to the
environment, we modify the generic function object to slot value mapping
to use the environment. This was supposed to be the essence of 2. Thus
information on methods being compiled can be stored in the generic function
object, but invocation of the generic function would get definitions
in the compiler's run time environment. This complicates the object to
slot value mapping somewhat, but avoids the problem with changing the
semantics of SYMBOL-FUNCTION. The idea is that the generic function
remembers the environment in which it was defined for funcalling purposes,
and otherwise uses the current environment for maintaining information
about definitions being compiled. Admittedly, this is a halfway solution,
but would involve less drastic modifications to Common Lisp, I think.
> However I object to 3 since it will make serious metaclass programming
> non portable.
It will restrict the class of object-object oriented languages which
can be portably implemented using the metaclass protocol to those which don't
require information on methods being compiled to be portably available
in the compile time environment. Note that CommonObjects is in this class,
and we have gotten around the problems by some monumental kludges and
some portable importabilities, ie., things which each implementor of
PCL needed to customize to their system. That particular part of
CommonObjects on CommonLoops was the most difficult to do, and the
one which breaks most often. The tradeoff for CLOS is that the metaclass
protocol would be simpler, and no modification of the base Common Lisp
semantics would be needed, meaning we could probably converge on a solution
more quickly.
∂03-Sep-87 1838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Sep 87 18:37:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 227853; Thu 3-Sep-87 21:39:00 EDT
Date: Thu, 3 Sep 87 21:38 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870903-141438-10242@Xerox>
Message-ID: <870903213846.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 3 Sep 87 14:14 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
I'll answer the rest of your message later, because I want to think a bit,
but the answer to this question is that functions defined with defmethod
receive their arguments in exactly the same way as functions defined with
defun. So it does whatever CLtL says and the implementation implements.
∂04-Sep-87 1058 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 87 10:58:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 87 08:56:41 PDT
Date: 4 Sep 87 08:56 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
23:17 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870904-085641-11164@Xerox>
Dick and I had a discussion about with-added-methods. We came to the
following conclusion about handling Case 3.
(with-added-methods <generic-function> (<methods>*) . <body>)
This takes a generic function and a list of methods specified as
lambda-expressions, creates a copy of the generic function and extends
it by adding the given methods. Within the lexical scope of the form,
(in <body>) appearances of <generic-function> refer to the extended
generic-function. with-added-methods does not affect the original
definition of <generic-function>.
This answers my question --
(defmethod fie (x) 0)
(defun foo (x)
(with-added-methods fie ((lambda ((x P1)) 17))
(cons (fie x) (fum x)))
(defun fum (y) (fie y))
(foo (make-instance 'P1)) ==> (17 . 0)
And it answers Pavel's query:
During the time that WITH-ADDED-METHODS is active, should the
other processes see the added methods or not? I would hope not!
Correct.
To obtain a special version of print with added methods, one uses
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
#'print)
and passes the returned generic function as an argument. Note that
since the generic function is copied on entry, this specialized print is
not affected by later global changes to the print generic function.
∂04-Sep-87 1112 Lanning.pa@Xerox.COM WITH-SLOTS, "virtual" slots, and the meta-object protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 87 11:12:21 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 87 11:10:36 PDT
Date: 4 Sep 87 11:10 PDT
Sender: Lanning.pa@Xerox.COM
From: Stanley's Tool Works <Lanning.pa@Xerox.COM>
Subject: WITH-SLOTS, "virtual" slots, and the meta-object protocol
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870904-111036-11421@Xerox>
Start with the standard x/y v rho/theta example:
(defclass position () (x y))
(defmethod rho ((p position)) ...)
(defmethod theta ((p position)) ...)
(defmethod-setf rho ((p position)) (value) ...)
(defmethod-setf theta ((p position)) (value) ...)
What if a user of the POSITION class writes the following method:
(defmethod zoom ((p position) n)
(with-slots (p)
(setf rho (* n rho))))
How is this going to work? Presumably the WITH-SLOTS macro consults the
class to find out what vars should be treated as slot references, but
the notion that RHO and THETA are slots has not been made explicit. How
does the writer of the POSITION class tell the class about these
"virtual" slots? Perhaps there should be macros that let you write
(defaccessor rho ((p position)) ...)
(defaccessor-setf rho ((p position)) ...)
or maybe a new method-qualifier so you could write
(defmethod rho :accessor ((p position)) ...)
(defmethod-setf rho :accessor ((p position)) ...)
I guess there could also be another class-option added to DEFCLASS, but
even if there were, something like these macros would be needed.
----- smL
∂08-Sep-87 1221 RPG WITH-ADDED-METHODS
To: common-lisp-object-system@SAIL.STANFORD.EDU
There is, I think, a better syntax for WITH-ADDED-METHODS
than what Danny sent out. That syntax was one we discussed
in the context of a slightly different semantics.
(with-added-methods ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
This takes the possibly already existing generic functions, FOO and BAR,
copies them, adds the new methods to them as specified, and then
executes <body>.
If no generic function exists, it is created. Previously defined generic
functions are not altered by the action of this construct.
The bindings of FOO and BAR have indefinite extent.
-rpg-
∂09-Sep-87 1124 Bobrow.pa@Xerox.COM Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 87 11:24:45 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 87 11:20:17 PDT
Date: 9 Sep 87 11:20 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Updating Obsolete Instances
To: common-lisp-object-system@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870909-112017-15101@Xerox>
One of the open questions we should resolve next week is what the
protocol should be for updating obsolete instances (instances of
obsolete classes). I present here a radically simpler proposal than the
ones we were most recently considering, though it bears strong
resemblance to some that were discussed earlier.
Proposal:
A class becomes obsolete when it is redefined (directly or indirectly),
the instance slots it specifies changes, AND it has one or more
instances. For classes that are instances of standard-class, we support
a protocol to update instances whose structure becomes obsolete.
If a class becomes obsolete, then we say its instances are obsolete
instances. Let c-new be the class specified by the new class definition.
Let obsolete-slots be the names of those slots that are not included in
the new definition, added-slots be the names of the new slots added, and
common-slots be the rest.
Effectively what happens is that all the obsolete instances become a
subclass of a newly defined class that has as direct-superclasses
(obsolete-class c-new). Hence, all methods applicable to instances of
the new class are applicable to the old instances.
However, the first time an attempt is made to access a slot-value of the
obsolete instance, the structure of the instance is updated to the
current structure before the slot-value completes. The updating is done
(effectively) as follows:
1) Values of all slots in the old instance are saved
2) The structure of the instance is made to correspond to the structure
specified by the current class definition (and it is an instance of
class c-new)
3) Values of all common-slots are inserted in the new instance structure
in the same named slot
4) The generic function obsolete-instance-updated is called. Its
arguments are the instance (now with the new structure) and a property
list containing the names and values of the obsolete-slots. There is a
method on standard-object for obsolete-instance-updated
(defmethod obsolete-instance-updated
((updated-instance standard-object) obsolete-slot-values)
...)
This method initializes (from initform) any slot in the new structure
that is not already bound. Slots without initforms are not touched.
Note that by specializing obsolete-instance-updated, one can do work
before or after, or instead of the initialization of unbound slots.
To enable users to cause instances to be updated without having to add a
phony slot, or some other abomination, we provide a generic-function:
(make-class-obsolete class)
with a method for standard-class that has the appropriate effect.
DISADVANTAGES
1) This proposal specifies that updating will not happen until a slot is
accessed. Perhaps this is too restrictive on implementations.
2) Methods applicable to the old class, but no longer current are not
usable.
3) This proposal does not support sequential updating of a chain of
obsolete structures. The only information it provides is the set of
obsolete-slots and values. We could make it possible to determine which
version of the obsolete class was involved in the update by passing the
obsolete-class as a second argument to updating-obsolete-instance. But
I don't think this is worth it.
ADVANTAGES
1) It specifies exactly when the update will happen, and hence is
guaranteed to minimize the work done; that is, no instance is updated
until it needs to be. It is possible to test if an instance is obsolete
by checing its type (seeing if its class is a subclass of
obsolete-class).
2) It ameliorates a problem we were discussing about how long what
methods must be kept around etc. No old versions of methods are kept.
3) It is simple to explain. Only one instance and class is involved in
updating-obsolete-instance, and the obsolete-slot information is passed
explicitly. The default behavior is what I claim is usually wanted.
∂09-Sep-87 1630 Bobrow.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 87 16:30:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 87 16:30:51 PDT
Date: 9 Sep 87 16:30 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 20 Aug 87 12:29 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870909-163051-15667@Xerox>
I propose that the DEFMETHOD macro be specified to "refer to"
(in the sense of CLtL p.160) each specialized parameter.
I think this is a fine idea.
One of the most common mistakes of beginning Lisp programmers
is omitting quote marks or putting them in the wrong place.
Actually, it's not only beginning programmers who do this. I still
do it myself sometimes, and I believe I have seen Danny Bobrow do
it.
I never do 'that'', do I??
The other problem with methods on individuals is that the
current syntax [for defmethod] is awkward when the individual is
anything other
than a symbol or a number
The intent was that for other cases, one would use the add-method form
which evaluates its arguments. However, I don't at all mind seeing a
change that makes defmethod easier to use for this case. And I agree
that evaluating the argument is useful, and using single quote may be a
more error prone as a syntax than a fully spelled keyword.
Of EQL and MEMBER, I prefer EQL since the form (MEMBER X) looks too easy
to extend with a Y and Z. But I would prefer not to suggest extensions
unless we are prepared to follow through on them soon. For this reason
some other word might be better. How about
(THIS x) as being mnemonic and short.
I think that adding QUOTE as a type-specifier to Common Lisp is
both unnecessary and confusing. (Yes, I know I suggested it. I
was wrong.) Instead, the parameter-specializer for a method on an
individual should be (MEMBER object), the type-specifier that
Common Lisp already defines for this purpose. Note that there is
no particular reason why the parameter-specializer should be the
same as the parameter-specializer-name; they're already not the
same for methods on classes.
A problem with this may be that the type specifier is used in the
specializers argument of add-method, and again this could lead to
unwarranted extrapolation. On the other hand, if you are using
add-method perhaps you are immune to unwarranted speculation.
∂09-Sep-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM User control of the CPL
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Sep 87 21:14:10 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 230758; Wed 9-Sep-87 22:43:07 EDT
Date: Wed, 9 Sep 87 22:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: User control of the CPL
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870909224238.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the
ordering of classes that only apply conditionally, i.e. if those
classes are actually present among the superclasses. He considers
this bad style. Moon volunteered to write a proposal with some
examples, and we agreed to resolve this over the mail.
PROPOSAL:
The :precedence option to defclass is written (:precedence C1 C2 C3 ...)
where the C's are class names. This specifies that C1 must precede C2
in the CPL, C2 must precede C3, etc. This defclass option may appear
any number of times.
The default if no :precedence option is specified for a class C with
direct superclasses C1, C2, ..., Cn is (:precedence C C1 C2 ... Cn). To
completely eliminate all precedence constraints, specify (:precedence C).
In the notation used on page 1-14 of 87-002, the :precedence option
allows direct control over Rc. Each ordered pair (C1,C2) in Rc is
specified by writing (:precedence C1 C2). :precedence with more than
two class names is simply a convenient abbreviation for multiple
:precedence options.
OPTIONS:
Optionally we could add an additional requirement that each Ci in a
:precedence option in the defclass for C must be either C or one of C's
direct superclasses. I am opposed to this, for reasons which should
become clear from the examples. It doesn't hurt to have extra ordered
pairs in Rc that do not affect the CPL. Another way of saying this is
that the :precedence option is useful both for relaxing the precedence
constraints, compared with the default, and for adding additional
constraints to the default constraints.
Optionally we could add an additional stipulation that regardless of the
use of :precedence options, a class always precedes its direct
superclasses. Specifically, in (defclass C (C1 C2 C3) () ...), the
effect of (:precedence C C1), (:precedence C C2), and (:precedence C C3)
is always present; in addition, if the user does not specify a
:precedence option, defclass supplies (:precedence C1 C2 C3). This
would slightly simplify the following section, but it seems like a
kludgey restriction on how much control over the precedence relations
the user is permitted. I have found applications that would not work
with this restriction, so I oppose adding this restriction.
Optionally we could add a restriction that a :precedence option in the
defclass for C may not specify that another class precedes C. Flavors
has such a restriction, however I believe it to be unnecessary and I
oppose making this restriction in CLOS.
EFFECT ON CPL ALGORITHM:
The first and third paragraphs on page 1-15 of 87-002 would need to be
changed. The statement "there can be only one such candidate class" is
no longer true once the user can relax the constraints using the
:precedence option. A more complex disambiguation rule is necessarily
required. I suggest replacing the first paragraph on 1-15 with:
Sometimes there are several classes from Sc with no predecessors. In
this case, we select one of these candidate classes according to the
following rule: Traverse the superclasses of each member of the CPL
found so far, associating the number (d*n*n)-(i*n)+b with the class at
depth d and breadth b in the tree rooted at the ith element of the CPL
found so far (make it a tree by considering only the first occurrence
in breadth-first order of each class). n is the number of classes
involved (the initial length of Sc). Choose the candidate with the
smallest associated number, considering the minimum if several numbers
are associated with one class. This algorithm selects a unique
candidate because no two associated numbers are equal.
A class is always the first element of its own CPL. Thus the CPL
computed so far, used in the above rule, can never be empty. This
implies an additional check: when computing the CPL of C, if (C',C) is
an element of R, signal an error reporting that it is invalid for C'
to precede C.
The above rule is the simplest rule I could find that is compatible with
the 87-002 rule. Other rules I considered were not compatible with the
87-002 rule and had additional undesirable properties. Note that in all
cases when the :precedence option is not used this rule produces the
same answer as the one in 87-002, and produces it in essentially the
same way. In this case d=1 for the winning candidate.
There are more efficient implementations than computing all the numbers
and then finding the minimum number, however that's the easiest way I could
find to explain it. An actual implementation could traverse all the trees
in parallel, in a suitable order, and take the first candidate it encounters.
Note that the last sentence in the first paragraph on 1-15 is irrelevant
to the paragraph and repeats what was already said in the last paragraph
on 1-14, so I would simply remove it.
The third paragraph on 1-15 could be replaced with a more precise
specification of the rule quoted above, if desired.
EXAMPLES:
For brevity I have omitted from R all pairs involving the class t.
;Two superclasses and we don't care about their order
;CPL=(example2 example super-2 super-1 t)
;R={(example-2,example),(example,super-1),(example,super-2),(super-2,super-1)}
(defclass example (super-1 super-2) ()
(:precedence example super-1)
(:precedence example super-2))
(defclass example-2 (example super-2 super-1) ())
;Two mixins that can be used separately but they interact and therefore
;if they are used together, they must be used in a certain order to work.
;Specifically, mixin-2 must be before mixin-1.
(defclass base-class () ())
(defclass use-1 (mixin-1 base-class) ())
(defclass use-2 (mixin-2 base-class) ())
(defclass use-both (mixin-1 mixin-2 base-class) ())
(defclass use-both-2 (use-1 use-2) ())
(defclass mixin-1 (base-class) ()
(:precedence mixin-2 mixin-1 base-class))
(defclass mixin-2 (base-class) ()
(:precedence mixin-2 mixin-1 base-class))
;use-1 and use-2 will not accidentally include the other mixin
;use-both will get an error for inconsistent precedence constraints
;use-both-2 will get a CPL of (use-both-2 use-1 use-2 mixin-2 mixin-1 base-class t)
;R={(use-both-2,use-1),(use-1,use-2),(use-1,mixin-1),(mixin-1,base-class),
; (use-2,mixin-2),(mixin-2,base-class),(mixin-2,mixin-1)}
;"Gross example" that helped me shoot down various other rules for
;resolving topological sort ambiguities
;CPL is (a c b e d t)
;R is {(a,b),(b,d),(c,b),(e,d)}.
(defclass a (b d) ())
(defclass b (c) ()
(:precedence b))
(defclass c () ()
(:precedence c b))
(defclass d (e) ()
(:precedence d))
(defclass e () ()
(:precedence e d))
;Two examples taken from actual (ugh, bletch) window code:
;This one shows two mixins that have an ordering constraint among them,
;but are not always used together. Rather than rely on any class that
;includes both to specify the constraint correctly, we specify it here.
;The user is adding more constraints to the default constraints.
(DEFCLASS DONT-SELECT-WITH-MOUSE-MIXIN (ESSENTIAL-WINDOW) ()
;; If TV:SELECT-MIXIN is present, we must
;; override its :NAME-FOR-SELECTION method
(:PRECEDENCE TV:DONT-SELECT-WITH-MOUSE-MIXIN
TV:SELECT-MIXIN
TV:ESSENTIAL-WINDOW))
;This one shows a class that is just a bundle of useful mixins, but doesn't
;want to constrain the order of those mixins.
;The user is specifying fewer than the default constraints
(DEFCLASS WINDOW (STREAM-MIXIN BORDERS-MIXIN LABEL-MIXIN SELECT-MIXIN
GRAPHICS-MIXIN MINIMUM-WINDOW) ()
;; The mixins already come with almost all necessary constraints.
;; Relax the constraints that would normally be implied by the above list
;; of components, so that subclasses of WINDOW can rearrange things.
;; Put the label inside the border.
(:PRECEDENCE BORDERS-MIXIN LABEL-MIXIN)
;; For esthetics, force WINDOW to precede MINIMUM-WINDOW
(:PRECEDENCE WINDOW MINIMUM-WINDOW))
∂10-Sep-87 1101 kempf%hplabsz@hplabs.HP.COM Meeting on Sept. 17-18
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 11:01:20 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 10 Sep 87 10:57:15 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 10 Sep 87 08:44:19 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 10 Sep 87 09:48:14 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Meeting on Sept. 17-18
X-Mailer: mh6.5
Date: Thu, 10 Sep 87 09:48:11 MST
Message-Id: <4135.558287291@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Has the location of the meeting next week been resolved? If so, could
someone post the place and time? Thanks.
jak
PS: Our phone connection in Andover was down for about a week, so
apologies if this information has already been posted.
∂10-Sep-87 1250 Bobrow.pa@Xerox.COM Re: Meeting on Sept. 17-18
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 12:50:19 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 SEP 87 12:50:44 PDT
Date: 10 Sep 87 12:50 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Meeting on Sept. 17-18
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 10 Sep 87
09:48:11 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870910-125044-16719@Xerox>
Jim,
The meeting will be at Xerox, starting at 9AM on Sept 17. Come to the
visitors entrance, and ask for me or Gregor. We will have some coffee,
juice and pastries in the room, as well as a recording whiteboard.
danny
∂10-Sep-87 2248 kempf%hplabsz@hplabs.HP.COM Trace Proposal (Version 2)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 22:47:54 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 10 Sep 87 19:54:27 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 10 Sep 87 13:12:34 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 10 Sep 87 14:16:56 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Trace Proposal (Version 2)
X-Mailer: mh6.5
Date: Thu, 10 Sep 87 14:16:53 MST
Message-Id: <7309.558303413@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Here is an updated draft of the debugging proposal. The proposal is on two
levels, a "command language" level for interactive use and a "metaobject
level" for implementation and easy language extension. The command language
level consists of the TRACE macro, for causing information
about the execution of funcallable objects to be displayed. The metaobject
level consists of a generic function, TRACE-EXECUTION,
for arranging, in an implementation dependent manner,
that this information be displayed. Note that the TRACE macro definition
is slightly incompatible with CLtL, since only one funcallable object at a
time can be specified. This was included to facilitate addition of
a :BREAK option, which, as Moon pointed out in his reply to the
original posting, would have been difficult with the original.
The CLtL UNTRACE macro would also be modified.
With regard to Moon's suggestion that the function-spec's are similar
to the proposed documentation or definition type, Larry Masinter indicated
that we should go ahead independently. However, I like the suggestion,
and have therefore modified the TRACE specification
to refer to the documentation type. In the event that no modification
of the current CLtL specification of documentation types is forthcoming
(or is delayed), the current one should be sufficient with
the addition of documentation types for CLOS entities and any for
implementation dependent tracable items (e.g. local functions).
This is noted in addition.
With regard to Moon's question about whether the following sequence:
(defun foo () ...)
(setq f #'foo)
(trace foo)
(funcall f)
generates trace output, the answer is, no. The intent of the
proposal is that when TRACE is used with a symbol as a function spec,
then invocations of the function are only traced when the function
is invoked via the definition in that symbol's global function cell.
Similarly, when TRACE-EXECUTION is called with a symbol and no
optional environment parameter, tracing occurs only when invocation
is through the symbol's global function cell. Implementations
may choose to provide tracing when a function is invoked through
application of the function definition object directly, or, as in the
case above, when the function definition is applied under another
name. In such an implementation, the above example could be rewritten
as:
(defun foo () ...)
(setq f #'foo)
(trace (function (symbol-function 'foo)))
(funcall f)
or the TRACE-EXCEUTION generic function could be called:
(trace-execution (symbol-function 'foo))
Thus, if an implementation is unable to support tracing through
the function definition object, the implementor could chose to
not support the FUNCTION function spec.
I hope we can discuss this at next week's meeting, if perhaps only
briefly in case there is not much time.
jak
Font information: UPPERCASE indicates bold, *word* indicates italics
--------------------------------------------------------------------------------
>>>>>>>>>>>>>
Addition to 87-002
>>>>>>>>>>>>>
TRACE *{function-spec}* &KEY (:BREAK NIL) *[Macro]*
UNTRACE *{function-spec}* *[Macro]*
Invoking TRACE with a function specification causes the
function specified to be traced. Henceforth whenever a specified
function is invoked, information about the call, the arguments passed,
and the returned values, if any, will be printed to the stream that is
the value of *TRACE-OUTPUT*. If the keyword argument :BREAK is T,
then the BREAK function will be called after the trace information
is printed. UNTRACE causes printing of trace information for the
specified function to cease.
A *function-spec* is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a documentation type, and
whose tail indicates which particular function of that type should
be traced. Documentation types are described in the description of
the DOCUMENTATION function. The complete set of documentation types,
and thus *function-specs*, will necessarily be implementation dependent,
however, here are several *function-specs* which every implementation is
required to support:
*symbol*-Invocation of the function named by *symbol* via. *symbol*'s
global function cell are traced.
(SETF *symbol* )-If the generalized variable reference indicated by
*symbol* is tracable, then invocations of the function implementing
the SETF operation will be traced.
(METHOD *generic-function-name* *parameter-specializer-name-list*)-
If the method whose parameter specializer list and generic function
name indicated is tracable, then invocations through the generic
function name will be traced.
(MACRO-FUNCTION *symbol*)-If *symbol* has a global macro function definition,
then invocations of the macro function through *symbol* will be traced.
Some *function-specs* which may be available in particular implementations
are:
(LOCAL-FUNCTION *symbol* *environment*)-Invocations of the lexically
defined function named *symbol* defined in *environment* are traced.
(LOCAL-MACRO-FUNCTION *symbol* *environment*)-Invocations of the lexically
defined macro named *symbol* defined in *environment* are traced.
(FUNCTION *function-definition-object*)-Invocations of the function
definition object are traced, regardless of whether through the global
function definition cell in a symbol or by direct application of the
function definition object.
Implementations are encouraged to provide for tracing as many kinds
of funcallable objects as possible.
>>>>>>>>>>>>>
Additions to the List of Documentation Types on pg. 440 of CLtL:
>>>>>>>>>>>>>
METHOD - returns documentation for methods defined with DEFMETHOD.
MACRO-FUNCTION - returns documentation for macros defined with DEFMACRO.
LOCAL-FUNCTION - returns documentation for functions defined with
FLET or LABELS.
LOCAL-MACRO-FUNCTION - returns documentation for macros defined with
MACROLET.
>>>>>>>>>>>>>
Addition to 87-003
>>>>>>>>>>>>>
TRACE-EXECUTION *object* &OPTIONAL *env* &KEY (:BREAK NIL) *[Generic Function]*
TRACE-EXECUTION discriminates on *object* to select an implementation
specific method that arranges for the executable entity associated
with *object* to be traced. The optional *env* environment parameter is for
those implementations which require environmental information to
arrange for tracing to occur. Implementations are required to provide
TRACE-EXECUTION as the system level entry point for implementing TRACE
functionality. If the :BREAK keyword argument is T, arrangement is made for
the BREAK function to be called after trace information is printed.
The exact nature and number of methods associated with TRACE-EXECUTION
will differ, depending on what function specifications are supported
by TRACE, but every implementation needs to support the following
methods:
SYMBOL-The function indicated by the symbol will be traced when invoked
in the environment. If the symbol names a function which is a globally
defined macro and no environment parameter is passed, then tracing will
occur when the global macro function is invoked. If the function definition
is bound to the symbol's global function definition cell and no environment
parameter is passed, then invocations of the function via. its global
name will be traced. If an environment argument is passed, then the symbol
is taken to name a local function or local macro function and only
invocations when the environment is the same as the environment parameter
will be traced, provided the implementation can arrange for it.
METHOD-The method function is traced when invoked.
GENERIC-FUNCTION-The generic function is traced when the discriminator
code is invoked.
Some methods which may be available in particular implementations
are:
FUNCTION-Invocation of the function is traced, regardless
of whether invocation is through a named symbol.
Implementations are encouraged to provide as many methods as is possible.
∂11-Sep-87 0827 skeene@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 08:27:40 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231837; Fri 11-Sep-87 11:28:56 EDT
Date: Fri, 11 Sep 87 11:28 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870820131023.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870911112819.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on mail received in response to the last time I mailed this out
(two weeks ago). If anyone doesn't see their response included, or
thinks their favorite issue is missing, please let me know and I will
apologize for my error and add it.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
We did decide this, and the document file reflects it. When I was
making these changes, I noticed that the only top-level form that
doesn't fit this model very well is DEFINE-METHOD-COMBINATION. I think
it should return the name of the type of method combination, not the the
object that represents the type of method combination. Programmers
never use method-combination object; they always use its name. The
reason we decided that DEFCLASS should return the class object (and so
on) is because the class object is useful. But the object representing
a method combination type is an implementation detail, and not useful to
the programmer.
I'd like to propose that we make an exception in this case, and have
DEFINE-METHOD-COMBINATION return the name of the method combination
type.
∂11-Sep-87 1023 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 10:23:23 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231942; Fri 11-Sep-87 13:24:41 EDT
Date: Fri, 11 Sep 87 13:24 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870911112819.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Message-ID: <870911132423.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 11 Sep 87 11:28 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
We did decide this, and the document file reflects it. When I was
making these changes, I noticed that the only top-level form that
doesn't fit this model very well is DEFINE-METHOD-COMBINATION. I think
it should return the name of the type of method combination, not the the
object that represents the type of method combination. Programmers
never use method-combination object; they always use its name. The
reason we decided that DEFCLASS should return the class object (and so
on) is because the class object is useful. But the object representing
a method combination type is an implementation detail, and not useful to
the programmer.
I'd like to propose that we make an exception in this case, and have
DEFINE-METHOD-COMBINATION return the name of the method combination
type.
The real problem here is that there is no object that represents a type
of method combination. In other words, the meta-object protocol does not
directly model method combination. Perhaps a meta-object theorist can
suggest how to fix this. Otherwise, I agree that DEFINE-METHOD-COMBINATION
should return the name.
∂11-Sep-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 10:34:19 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231964; Fri 11-Sep-87 13:35:32 EDT
Date: Fri, 11 Sep 87 13:34 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911133455.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
The following text came from Moon's message on Miscellaneous Decisions:
----------
2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
----------
It's not clear to me who suggested putting the short form of
DEFINE-METHOD-COMBINATION into the library, but I strongly disagree
with the idea.
The short form of DEFINE-METHOD-COMBINATION satisfies the design goal of
"providing simple ways to do simple things". Many, probably most, of
the commonly-needed types of method combination can be defined that way,
with one line of code.
The way I see it, CLOS is organized in two levels.
The Programmer Interface is sufficient for most programmers to do most
things they need to do. The Meta-Object protocol lets programmers do
almost anything they could ever want to do, but it requires extra
effort. Many aspects of the programmer interface are just convenience
features, in that the programmer could achieve the same effect, with
greater effort, using the Meta-object operators. However, the
programmer interface is here because it makes CLOS much more usable.
Similarly, DEFINE-METHOD-COMBINATION has two levels -- the short form
and the long form. The short form is just a convenience feature for
the long form, but it makes declarative method combination much more
usable. I don't see any advantage in removing it from the CLOS
standard.
∂11-Sep-87 1154 Bobrow.pa@Xerox.COM [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 11:53:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 11:48:09 PDT
Date: 11 Sep 87 11:47 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870911-114809-18010@Xerox>
To: Danny Bobrow <Bobrow.pa>
Subject: Re: Updating Obsolete Instances
X-Mailer: mh6.5
In-Reply-To: Your message of 09 Sep 87 11:20:00 -0700.
<870909-112017-15101@Xerox>
Date: Thu, 10 Sep 87 18:14:39 MST
Message-Id: <9967.558317679@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
General comments: This proposal seems to simplify class changing
and instance updating considerably. It is certainly the simplest
and most direct proposal advanced so far, and reduces the amount
of overhead for class changing.
> A class becomes obsolete when it is redefined (directly or indirectly),
> the instance slots it specifies changes, AND it has one or more
> instances. For classes that are instances of standard-class, we support
> a protocol to update instances whose structure becomes obsolete.
If the class has no instances, does it simply become undefined?
Assuming this is so, it should be added to the spec. Also,
need the change class protocol be applied to a class in which none
of the slot definitions have changed?
> Effectively what happens is that all the obsolete instances become a
> subclass of a newly defined class that has as direct-superclasses
> (obsolete-class c-new). Hence, all methods applicable to instances of
> the new class are applicable to the old instances.
Very nice! This would take care of the problem of how to have the methods
applicable for the new class do the updating without impacting method
invocation performance on new instances, nor requiring classes to keep
pointers to all instances created.
> However, the first time an attempt is made to access a slot-value of the
> obsolete instance, the structure of the instance is updated to the
> current structure before the slot-value completes. The updating is done
> (effectively) as follows:
> 1) Values of all slots in the old instance are saved
> 2) The structure of the instance is made to correspond to the structure
> specified by the current class definition (and it is an instance of
> class c-new)
> 3) Values of all common-slots are inserted in the new instance structure
> in the same named slot
> 4) The generic function obsolete-instance-updated is called. Its
> arguments are the instance (now with the new structure) and a property
> list containing the names and values of the obsolete-slots. There is a
> method on standard-object for obsolete-instance-updated
> (defmethod obsolete-instance-updated
> ((updated-instance standard-object) obsolete-slot-values)
> ..)
> This method initializes (from initform) any slot in the new structure
> that is not already bound. Slots without initforms are not touched.
What about a change in allocation type? For example, if the old
class had a slot whose allocation was :INSTANCE and the new :CLASS,
then does SLOT-VALUE on this slot return the new :CLASS allocated
value? If so, then DEFCLASS or OBSOLETE-INSTANCE-UPDATED should at least warn
the user that the allocation type has changed. Similarly for an
old :CLASS allocation changing to :INSTANCE. Also, if the :TYPE option
is used to type a new slot with a type which is incompatible with
the old, the user should be warned.
> To enable users to cause instances to be updated without having to add a
> phony slot, or some other abomination, we provide a generic-function:
> (make-class-obsolete class)
> with a method for standard-class that has the appropriate effect.
Yes, this is definitely needed.
> DISADVANTAGES
> 2) Methods applicable to the old class, but no longer current are not
> usable.
I don't quite understand this. What do you mean by "current"?
> 3) This proposal does not support sequential updating of a chain of
> obsolete structures. The only information it provides is the set of
> obsolete-slots and values.
Since updating is hookable, users can do this themselves if they want.
Another disadvantage is that methods which use WITH-SLOTS will
still have references to slots which no longer exist, although
attempting to reference those slots will cause the instance to
update itself. But this will also be true if the slot accessor functions
are used directly, since they will be undefined when the new class
is defined without the old slots.
An additional problem is that the obsolete classes will remain hanging
around even after all the instances are updated, unless they and the
update methods are keeping track of the number of instances around,
and they can undefine themselves once all instances are updated.
Note this won't require them to keep track of instances, just the
number created.
Looking at the semantic difficulties section on pg. 2-9 for CHANGE-CLASS,
the difficulties with changing an instance inside a method seem to
be eliminated, since, although the class changes, all methods
applicable before the change are still applicable afterwards, since
the class precedence list is only being shortened from the more
specialized end. This means that the effective method calculation
need not be redone. Problems with optimizing slot access will
still occur, but the specification for WITH-SLOTS should probably
indicate that optimization at level 3 will not remove access
through the SLOT-VALUE function unless safety is also set to 0.
Finally, it would probably be a good idea to drastically limit what the
user can do with an obsolete class, like not letting the user create an
instance of it directly. Should the user be allowed to cause an obsolete class
to become current again? My general inclination is to say probably
not. This would drift into undo-like facilites, which are best left
to the programming environment. Also, it would definitely not be
a good idea to allow use of the obsolete class as a parameter
specializer, nor to inherit from it, otherwise the semantic difficulties
with methods could recur, since the set of applicable methods and
effective method might change during method application.
----- End Forwarded Messages -----
danny
∂11-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 11:54:06 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 11:48:45 PDT
Date: 11 Sep 87 11:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Updating Obsolete Instances
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 10 Sep 87
18:14:39 MST
To: common-lisp-object-system@sail.stanford.edu
cc: Bobrow.pa@Xerox.COM,kempf%hplabsz@hplabs.HP.COM
Message-ID: <870911-114845-18011@Xerox>
> A class becomes obsolete when it is redefined (directly or
> indirectly), the instance slots it specifies changes,
> AND it has one or more instances. For classes that are
> instances of standard-class, we support a protocol
> to update instances whose structure becomes obsolete.
If the class has no instances, does it simply become undefined?
No, it simply becomes redefined. The only reason to obsolete a class is
so that instances can be updated. One can radically redefine a class
that has no instances, and no obsolete class need be created.
What about a change in allocation type? For example, if the old
class had a slot whose allocation was :INSTANCE and the new :CLASS,
then does SLOT-VALUE on this slot return the new :CLASS allocated
value?
Changing an aloocation from :instance to :class of course makes a class
obsolete (if it has instances). This was supposed to be covered by the
phrase "the instance slots it specifies changes". Simlarly for the
change the other way. SLOT-VALUE on this slot should return the new
:CLASS allocated value in any methods.
DEFCLASS or OBSOLETE-INSTANCE-UPDATED should at least warn the
user that the allocation type has changed.
I don't understand the general Common Lisp policy about warnings. When
should DEFCLASS warn? Does DEFUN warn when it is redefining a function?
I don't think OBSOLETE-INSTANCE-UPDATED should ever warn, since clearly
this is dominated by the warning about change of the class.
Also, if the :TYPE option is used to type a new slot with a
type which is incompatible with the old, the user should be warned.
This need not cause a class to be obsoleted. It might cause the
accessors to be updated if they are the ones that check the type.
We do need to decide if an error is signalled if
(sef (slot-value ...)...)
tries to violate a type restriction.
> DISADVANTAGES
> 2) Methods applicable to the old class, but no longer current
> are not usable.
I don't quite understand this. What do you mean by "current"?
I was referring to an earlier discussion where it was suggested that
methods that were applicable to old instances, but have since been
changed or deleted be kept for use with the now obsolete instances. For
example, if the definition of point changed from using x and y, to using
rho and theta, the method that computed rho would no longer be needed
(should be replaced by a simple accessor). Would the old computation be
kept around. I am answering this with a NO.
Another disadvantage is that methods which use WITH-SLOTS will
still have references to slots which no longer exist, although
attempting to reference those slots will cause the instance to
update itself. But this will also be true if the slot accessor
functions are used directly, since they will be undefined when the
new class is defined without the old slots.
I think this is intrinsic to any redefinition of a class.
An additional problem is that the obsolete classes will remain
hanging around even after all the instances are updated, unless
they and the update methods are keeping track of the number of
instances around, and they can undefine themselves once all
instances are updated. Note this won't require them to keep track
of instances, just the number created.
This might be handled by the garbage collector. If there is no pointer
maintained from a superclass to an obsolete subclass, and obsolete
classes have no name, then the only pointers to the obsolete class will
be in the instances. When there are no more instances, the obsolete
class will be collected.
Looking at the semantic difficulties section on pg. 2-9 for
CHANGE-CLASS
I did not propose that this protocol for obsoleteinstances replace the
CHANGE-CLASS protocol. I have always thought it a mistake to confound
these two cases. For CHANGE-CLASS, both the classes involved are still
current (not obsolete), and hence a CLASS-CHANGED method can be called.
The difficulties with changing an instance inside a method seem
to be eliminated, since, although the class changes, all methods
applicable before the change are still applicable afterwards, since
the class precedence list is only being shortened from the more
specialized end.
For CHANGE-CLASS, the user can change an instance of any class to any
other (e.g. from a window to an automobile) and the only guaraneed
intersection of the class precedence list is OBJECT.
Problems with optimizing slot access will still occur, but the
specification for WITH-SLOTS should probably indicate that
optimization at level 3 will not remove access through the
SLOT-VALUE function unless safety is also set to 0.
There are numerous problems with fully optimized slot-value calls. In
another message I propose a protocol to deal with this problem.
Finally, it would probably be a good idea to drastically limit
what the user can do with an obsolete class, like not letting the
user create an instance of it directly. Should the user be allowed
to cause an obsolete class to become current again? My general
inclination is to say probably not. This would drift into
undo-like facilites, which are best left to the programming
environment. Also, it would definitely not be a good idea to allow
use of the obsolete class as a parameter specializer, nor to
inherit from it, otherwise the semantic difficulties with methods
could recur, since the set of applicable methods and effective
method might change during method application.
I agree. Obsolete classes should resist all changes including
production of new instances. This probably requires an
obsolete-metaclass as well as an obsolete-class to implement cleanly.
∂11-Sep-87 1204 skeene@STONY-BROOK.SCRC.Symbolics.COM proposal for arguments for call-next-method
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 12:04:35 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 232100; Fri 11-Sep-87 15:05:48 EDT
Date: Fri, 11 Sep 87 15:05 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: proposal for arguments for call-next-method
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911150510.5.SKEENE@JUNCO.SCRC.Symbolics.COM>
Character-Type-Mappings: (1 0 (NIL 0) (NIL :ITALIC NIL) "CPTFONTI")
Fonts: CPTFONT, CPTFONTI
In July we agreed that call-next-method should take arguments. I
gathered together information from the various messages and came up with
the following text, which I propose should go into the CALL-NEXT-RECORD
section in Chapter 2. This text doesn't deal with other issues about
CALL-NEXT-METHOD, such as the dynamic extent or CALL-NEXT-METHOD-OR-NIL
issues.
--------------------
When {\bf call-next-method} is called with no arguments, it passes the
current method's original arguments to the next method. Neither
argument defaulting, nor using {\bf setq}, nor rebinding variables with
the same names as parameters of the method affects the values {\bf
call-next-method} passes to the method it calls.
When {\bf call-next-method} is called with arguments, the next method is
called with those arguments. When providing arguments to {\bf
call-next-method}, the following rule must be satisfied or an error is
signalled: The set of methods applicable for a changed set of arguments
for {\bf call-next-method} must be the same as the set of applicable
methods for the original arguments to the method.ε1 ε0 If {\bf call-next-method}
is called with arguments but omits optional arguments, the next method
defaults those arguments. Optimizations of the error checking are possible
but they should be invisible to the programmer.
∂11-Sep-87 1314 Bobrow.pa@Xerox.COM Deoptimizing Slot Access
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 13:14:06 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 13:14:37 PDT
Date: 11 Sep 87 13:14 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Deoptimizing Slot Access
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
Message-ID: <870911-131437-18190@Xerox>
The metaclass protocol provides for a mechanism whereby implementations
can optimize slot access for instances of certain classes. This
protocol is discussed in another message. This message is concerned
with a related problem.
Suppose we have
(defclass c1 () (x y))
and
(defmethod m1 ((i c1)) (slot-value i 'x))
and the latter method is compiled so that slot-access is optimized.
The suppose we define:
(defclass c2 (c1)
((x :allocation :special))
(:metaclass special-class))
where for classes with metaclass special-class, slot access for slots
with allocation :special it is inappropriate to use the optimized code.
Then in order to make method m1 usable for instances of class c2, it
would be nice to be able to cause a trap in the optimized code for
accessing that slot for instances of c2. We propose that there be a
standard way to cause this to happen for methods originally defined on
instances of standard class, and that the trap call
slot-value-using-class.
We propose two generic functions in the metaobject protocol associated
with this behaviour. The contract for each and the methods for
standard-class are described below:
deoptimize-slot-accesses (class slotd)
Calling this generic-function on an instance <class> of
standard-class and <slotd> of standard-slot-description will ensure
that, in any method applicable to instances of <class>, all accesses to
the slot described by <slotd> in <class> will call
slot-value-using-class. If this is not possible for these arguments, an
error is signalled.
For standard-class, an error will be signalled only if slotd is not a
slot in the class.
can-deoptimize-slot-accesses-p (class slot-description)
Returns T if deoptimize-slot-access will not signal an error.
This facility could be used to implement the cahnge in access when a
slot allocation is changed for a particular slot from :instance in a
superclass to :class in a subclass.
Methods specialized on classes are recorded. If one allows slot access
to be optimized for uses of with-slots in functions not specialized on a
class, then all such uses must be recorded so that they can be found by
deoptimize-slot-accesses.
∂11-Sep-87 1335 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 13:35:44 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 13:35:19 PDT
Date: 11 Sep 87 13:35 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 9 Sep 87 22:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870911-133519-18239@Xerox>
If we wanted to have an additional mechanism for controlling the set of
pairs in partial order that determines the class precedence list, then I
suppose this proposal is a reasonable one. However, after looking at
the examples, I felt that the gain in potential simplicity for people
who wanted to exert indirect control over the class precedence list is
more than offset by the extremely nonintuitive (to me) behaviors that
are possible to obtain from this yet another programming language.
The example for the window system would better be done by a special
program that knows how to construct window classes out of descriptions
of desired behaviors. Assuming that users know an entire complex of
class names but not about constraints among class use seems an
inappropriate intermediate position. Naive users who want to construct
a mix and match window class ought to be given a mini-expert system to
help, because constraints can easily be more than those simply
resolvable by class ordering.
∂11-Sep-87 1447 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: User control of the CPL
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 14:47:24 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 232298; Fri 11-Sep-87 17:42:39 EDT
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: User control of the CPL
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870911-133519-18239@Xerox>
Message-ID: <870911174243.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a special
program that knows how to construct window classes out of descriptions
of desired behaviors.
I don't see why the fact that the Zetalisp window system is badly designed
should be a design criterion for CLOS. I only included those examples
because for me it was a convenient source of examples drawn from a real
program.
∂11-Sep-87 1641 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Updating Obsolete Instances
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:41:05 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah03509; 11 Sep 87 19:25 EDT
Received: from ti-csl by RELAY.CS.NET id ah01016; 11 Sep 87 19:18 EDT
Received: from Jenner by tilde id AA08017; Fri, 11 Sep 87 17:42:43 CDT
Message-Id: <2767387349-12962022@Jenner>
Date: Fri, 11 Sep 87 17:42:29 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Updating Obsolete Instances
In-Reply-To: Msg of 9 Sep 87 11:20 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
If a class becomes obsolete, then we say its instances are obsolete
instances. Let c-new be the class specified by the new class definition.
Let obsolete-slots be the names of those slots that are not included in
the new definition, added-slots be the names of the new slots added, and
common-slots be the rest.
I am confused here. Are you giving up the fact that c-new is eql to the
class object existing just before the redefinition?
Effectively what happens is that all the obsolete instances become a
subclass of a newly defined class that has as direct-superclasses
(obsolete-class c-new). Hence, all methods applicable to instances of
the new class are applicable to the old instances.
I am confused here too. Do you mean that obsolete-class does not have
any method applicable to it?
3) This proposal does not support sequential updating of a chain of
obsolete structures. The only information it provides is the set of
obsolete-slots and values. We could make it possible to determine which
version of the obsolete class was involved in the update by passing the
obsolete-class as a second argument to updating-obsolete-instance. But
I don't think this is worth it.
I think that supporting sequential update is important. With machines
able to run weeks instead of hours without running out of memory or
crashing, people will want to redefine existing classes without having
to think about the ten previous updates while writing their
obsolete-instance-updated method.
∂11-Sep-87 1657 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:57:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 16:57:55 PDT
Date: 11 Sep 87 16:57 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 17:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-165755-1193@Xerox>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a
special program that knows how to construct window classes out
of descriptions of desired behaviors.
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon
I don't see why the fact that the Zetalisp
window system is badly designed should be a design criterion for
CLOS. I only included those examples because for me it was a
convenient source of examples drawn from a real program.
I did not mean to criticize the window system design (I didn't think you
were defending it). It was a good example to show how constraints
between classes might arise naturally.
But I don't think that complex constructions of that kind (even for a
well designed system) can or should be mediated by a very simple set of
ordering constraints. If there are only one or two extra ordering
constraints, then combined classes that embody the combined order
constraint in the superclass order will do, and if it is more complex
than that, then a real interactive system for construction from parts
would be more appropriate, I think.
∂11-Sep-87 2030 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:57:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 16:57:55 PDT
Date: 11 Sep 87 16:57 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 17:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-165755-1193@Xerox>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a
special program that knows how to construct window classes out
of descriptions of desired behaviors.
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon
I don't see why the fact that the Zetalisp
window system is badly designed should be a design criterion for
CLOS. I only included those examples because for me it was a
convenient source of examples drawn from a real program.
I did not mean to criticize the window system design (I didn't think you
were defending it). It was a good example to show how constraints
between classes might arise naturally.
But I don't think that complex constructions of that kind (even for a
well designed system) can or should be mediated by a very simple set of
ordering constraints. If there are only one or two extra ordering
constraints, then combined classes that embody the combined order
constraint in the superclass order will do, and if it is more complex
than that, then a real interactive system for construction from parts
would be more appropriate, I think.
∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 17:52:06 PDT
Date: 11 Sep 87 17:52 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Updating Obsolete Instances
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 11 Sep 87 17:42:29 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911-175206-1258@Xerox>
If a class becomes obsolete, then we say its
instances are obsolete instances. Let c-new be the class
specified by the new class definition. Let obsolete-slots be
the names of those slots that are not included in the new
definition, added-slots be the names of the new slots added,
and common-slots be the rest.
I am confused here. Are you giving up the fact that c-new is
eql to the class object existing just before the redefinition?
No. I should have been more explicit. c-new is EQL to the original
class, but has the new description.
Effectively what happens is that all the obsolete
instances become a subclass of a newly defined class that has
as direct-superclasses (obsolete-class c-new). Hence, all
methods applicable to instances of the new class are
applicable to the old instances.
I am confused here too. Do you mean that obsolete-class does
not have any method applicable to it?
The only method on obsolete-class that I know about is
slot-value-using-class, and it causes the updating to happen.
3) This proposal does not support sequential updating
of a chain of obsolete structures. The only information it
provides is the set of obsolete-slots and values. We could
make it possible to determine which version of the obsolete
class was involved in the update by passing the obsolete-class
as a second argument to updating-obsolete-instance. But I
don't think this is worth it.
I think that supporting sequential update is important. With
machines able to run weeks instead of hours without running out of
memory or crashing, people will want to redefine existing classes
without having to think about the ten previous updates while
writing their obsolete-instance-updated method.
I am not convinced that people would really use this. My model is that
they would continue to edit the obsolete-instance-updated each time if
there was significant work to do; and most of the time the obsolete
instances would probably not be used, even if the classes changed often.
But of course I am flaming about "usual programming practice". For
Loops, we had the simplest version of this feature (it always just saved
obsolete slot values on a property list), and we had no complaints. I
often ran in the same image for a week or two at a time, doing extensive
development.
∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 17:41:24 PDT
Date: 11 Sep 87 17:41 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:24 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-174124-1245@Xerox>
I'd like to propose that we make an exception in this
case, and have DEFINE-METHOD-COMBINATION return the name of
the method combination type.
The real problem here is that there is no object that
represents a type of method combination. In other words, the
meta-object protocol does not directly model method combination.
Perhaps a meta-object theorist can suggest how to fix this.
Otherwise, I agree that DEFINE-METHOD-COMBINATION should return the
name.
As a representative of the meta-theorist camp, I want to agree that the
appropriate thing to return in this case is the name.
danny
∂11-Sep-87 2058 Bobrow.pa@Xerox.COM Re: short form of define-method-combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 18:45:11 PDT
Date: 11 Sep 87 18:45 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: short form of define-method-combination
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:34 EDT
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911-184511-1302@Xerox>
It's not clear to me who suggested putting the short form of
DEFINE-METHOD-COMBINATION into the library, but I strongly disagree
with the idea.
I cannot tell a lie. It was I.
The short form of DEFINE-METHOD-COMBINATION satisfies the
design goal of "providing simple ways to do simple things". Many,
probably most, of the commonly-needed types of method combination
can be defined that way, with one line of code.
Are there other simple cases other than ones that are predefined e.g.
:and :append ...? I thought you had already defined the useful ones
(REF Symbolic manual).
The Programmer Interface is sufficient for most programmers to
do most things they need to do.
I am suggesting that a library that is first class (it consists of
standard implementations of useful things) be included with the
standard. The rule should be, if an implementation includes a feature
like this (has the same name) it should be equivalent to this one.
Library programs would be straightforward programming excercises for
some of the less frequently used programming tools. In addition to
DEFINE-METHOD-COMBINATION in the short form, I would put in there
functions like
all-class-slot-names class &optional allocation
and other simple uses of mapcar over some of the basic data structures.
We can even add something like classes to implement active values, slot
properties, dynmaic slots, and a few other of the features that we took
out of the standard but a significant number of users seem to be
reinventing.
I don't see any advantage in removing it from the CLOS
standard.
The advantage I see is that it allows us another level beyond the basic
programmer's interface. There is a three level structure
1) Metaobject protocol (fine grain control of the implementmentation)
2) Programmers Interface (what I use everyday)
3) Programmer's library (Useful things I might do on accasion)
If we can make level 3 real for CLOS (meaning it is as standardized as
the spec -- but is in a library), perhaps we can even push this idea
into Common Lisp itself.
∂14-Sep-87 1346 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 13:46:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 13:43:33 PDT
Date: 14 Sep 87 13:43 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:24 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-134333-2880@Xerox>
Well, if you believe that define-method-combination expands something
like this:
(define-method-combination AND ..) ==>
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
(type (eql 'and))
..)
..)
Then the appropriate object would be the method on
compute-effective-method-internal or whatever the name of the generic
function the following method is documented to call.
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
..)
(compute-effective-method-internal
generic-function
(slot-value generic-function 'method-combination-type)
..))
∂14-Sep-87 1439 Bobrow.pa@Xerox.COM Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 14:39:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 14:39:45 PDT
Date: 14 Sep 87 14:39 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Uninitialized Slots
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-143945-2999@Xerox>
Moon noted:
2-19 uninitialized slots should be an error to reference, not
be defined to return an unstandardized value with no error. I'm
willing not to require that it signals an error if people feel that
would be an undue burden, otherwise I prefer that reading an
uninitialized slot signals an error.
In July we decided that signalling an error here should
depend on the declared safety level.
Rather than signal an error directly, I propose that a generic-function
be called, dependent in the same way on safetty level:
slot-uninitialized (class instance slot-name)
where class is the class of the instance. The method on standard-class
signals an error. Among other things, this allows an easy implementation
of default values in classes, a current feature of Loops, Strobe and
KEE.
∂14-Sep-87 1446 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 14:46:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233579; Mon 14-Sep-87 17:47:10 EDT
Date: Mon, 14 Sep 87 17:47 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-134333-2880@Xerox>
Message-ID: <870914174715.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 13:43 PDT
From: Gregor.pa@Xerox.COM
Well, if you believe that define-method-combination expands something
like this:
(define-method-combination AND ..) ==>
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
(type (eql 'and))
..)
..)
Then the appropriate object would be the method on
compute-effective-method-internal or ....
I disagree. That method object is -part of the implementation of- the
method combination type, but it does not -represent- the method
combination type in the same sense that a class object -represents- a
class and a method object -represents- a method, in the meta-object
world's -model- of what the system is doing. Switching to speaking
operationally from speaking philosophically, there aren't operations on
that method object that will tell you things about the
method-combination type. If I'm wrong here then I -really- don't
understand meta-objects (which is of course possible).
∂14-Sep-87 1510 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:10:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 15:11:01 PDT
Date: 14 Sep 87 15:10 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 14 Sep 87 17:47 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-151101-3059@Xerox>
No, I think you are right, that method object doesn't really represent
the method combination type. I was kind of kidding.
BUT, if as part of a particular implementation, you decided to store the
information which "represents" the method combination type as some
datastructure rather than just having it be 'inline' in the code of the
method; storing it in the method object might be reasonable.
That sentence is contorted, but what I mean is that both of the
following expansioons for define-method-combination are reasonable:
(define-method-combination :FOO ..)
(defmethod mumble (..)
(let ((info (GET ':FOO 'METHOD-COMBINATION-TYPE)))
...)))
(let ((method (make-instance 'dmc-method ...)))
(setf (method-function method)
#'(lambda (..)
(let ((info (SLOT-VALUE METHOD 'INFO))) ..)))
(add-method #'mumble method))
Of course in the second example, the stuff stored inside the method is
just a "random" structure in the same way the stuff stored on the plist
is. I am just trying to show that the documented existence of the
method object can be used like this to hold the structure. This also
make it possible for the GC to collect that "random structure" if the
method is dropped on the floor.
∂14-Sep-87 1511 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized Slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:11:45 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233609; Mon 14-Sep-87 18:12:28 EDT
Date: Mon, 14 Sep 87 18:12 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Uninitialized Slots
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-143945-2999@Xerox>
Message-ID: <870914181233.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 14:39 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon noted:
2-19 uninitialized slots should be an error to reference, not
be defined to return an unstandardized value with no error. I'm
willing not to require that it signals an error if people feel that
would be an undue burden, otherwise I prefer that reading an
uninitialized slot signals an error.
In July we decided that signalling an error here should
depend on the declared safety level.
Rather than signal an error directly, I propose that a generic-function
be called, dependent in the same way on safetty level:
slot-uninitialized (class instance slot-name)
where class is the class of the instance. The method on standard-class
signals an error. Among other things, this allows an easy implementation
of default values in classes, a current feature of Loops, Strobe and
KEE.
I'm happy with this. I'll edit it into the document from which "Moon noted"
came (I hope tonight to mail out the last version of that document before
this week's meeting).
∂14-Sep-87 1532 kempf%hplabsz@hplabs.HP.COM Re: User control of the CPL
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:31:05 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 14 Sep 87 15:25:16 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 14 Sep 87 15:52:50 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: User control of the CPL
X-Mailer: mh6.5
In-Reply-To: Your message of Wed, 09 Sep 87 22:42:00 -0400.
<870909224238.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 14 Sep 87 15:52:46 MST
Message-Id: <4795.558654766@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> The default if no :precedence option is specified for a class C with
> direct superclasses C1, C2, ..., Cn is (:precedence C C1 C2 ... Cn). To
> completely eliminate all precedence constraints, specify (:precedence C).
> In the notation used on page 1-14 of 87-002, the :precedence option
> allows direct control over Rc. Each ordered pair (C1,C2) in Rc is
> specified by writing (:precedence C1 C2). :precedence with more than
> two class names is simply a convenient abbreviation for multiple
> :precedence options.
It sounds from this that you are thinking here about controlling the
local precedence order using the :PRECEDENCE option (please correct
me if I'm wrong), but I don't think that's necessary. A user can control
the local precedence order by simply changing the order of the supers
in the super list. The problems come when trying to impose some kind of
global control over the CPL.
> Optionally we could add an additional requirement that each Ci in a
> :precedence option in the defclass for C must be either C or one of C's
> direct superclasses. I am opposed to this, for reasons which should
> become clear from the examples. It doesn't hurt to have extra ordered
> pairs in Rc that do not affect the CPL. Another way of saying this is
> that the :precedence option is useful both for relaxing the precedence
> constraints, compared with the default, and for adding additional
> constraints to the default constraints.
See comment above.
> Optionally we could add an additional stipulation that regardless of the
> use of :precedence options, a class always precedes its direct
> superclasses. Specifically, in (defclass C (C1 C2 C3) () ...), the
> effect of (:precedence C C1), (:precedence C C2), and (:precedence C C3)
> is always present; in addition, if the user does not specify a
> :precedence option, defclass supplies (:precedence C1 C2 C3). This
> would slightly simplify the following section, but it seems like a
> kludgey restriction on how much control over the precedence relations
> the user is permitted. I have found applications that would not work
> with this restriction, so I oppose adding this restriction.
I tend to think that this stipulation may be necessary, however, I'm
open to examples where it may not. From my reading of the examples
included at the end of the base note, I couldn't find any where
this stipulation would make the example not possible. The reason I think it
should be included is that I think it fits the mental model of inheritance as
specialization, which is how I think we'd like to encourage people to
think about inheritance in the default CLOS language. If people want
to use the metaobject protocol to write their own inheritance algorithm,
then they should be able to do whatever they want. People who want to
think about inheritance differently can write a CALCULATE-CLASS-PRECEDENCE
-LIST method customized to do things differently.
Also, putting in this stipulation (e.g. a class always preceeds it's
direct superclasses) reinforces the concept of local precedence order,
which means that programmers can deal with a class and its superclasses
as a kind of logical unit.
>>>>>>>>
While I'm not sure about this particular proposal, I am in favor of
some kind of user control over the CPL calculation, but for different
reasons. For the case where the inheritance graph cannot be linearized,
the user should be given the option of being able to control the
linearization and specify the global precedence ordering when conflicts
occur, without having to write a CALCULATE-CLASS-PRECEDENCE-LIST method.
Whether this control comes in the form of a continuable error when
the default algorithm fails (in which case, the user is invited to
supply a consistent list, perhaps interactively) or as a class option
in which the user supplies some global precedence constraint or some
other way is not that important, as long as it fits in well with
the rest of CLOS. Some form of control is needed, however.
Additionally, the class freezing proposal which was briefly
discussed last spring as an optimization procedure would be another
case where a user controlled the CPL calculation. In that case,
the CPL of a "frozen" class would need to be treated as a unit for
any subclass inheriting from the frozen class. The result would be
the same as a user defined constraint on the CPL, except the constraint
would be on the entire CPL of the super and not on a subsection.
There are other aspects to class freezing as well
(disallowing redefinitions for example).
It would be nice if both these needs could be united into
one, perhaps with a new generic function or macro in the user interface
section which gives the user control over the CPL (or part thereof)
in a manner consistent with the rest of the user level language, rather
than a new constraint language, but maybe that's hoping for too much.
For random changes to the CPL, I think that using the metaobject protocol
would probably be best.
jak
∂14-Sep-87 1547 Masinter.pa@Xerox.COM Re: Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:47:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 15:47:28 PDT
Date: 14 Sep 87 15:47 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Uninitialized Slots
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 14 Sep 87 18:12 EDT
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-154728-3159@Xerox>
There are really serious problems with having a well-defined operation
(like calling slot-uninitialized) depend on the "declared safety level".
The only things that should depend on the declared safety level are
whether an error is signalled when it "should be". Otherwise, the safety
level must enter into the language semantics rather than being just a
"hint".
∂14-Sep-87 1642 Bobrow.pa@Xerox.COM Re: Agenda for September meeting
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 16:42:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 16:42:35 PDT
Date: 14 Sep 87 16:42 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Agenda for September meeting
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 18 Aug 87 14:46 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870914-164235-3253@Xerox>
Discuss written proposals on major areas, circulated over the
network before the meeting and brought to the meeting in hardcopy.
A number of proposals have appeared over the network. How should they
appear in hardcopy. Do you intend to extract what you think are the
current proposals, or should we have distributed resposnsibility. Seems
like the latter is fairer, but we ought to have a list of the expected
proposals. Do you have a list of such proposals that need separate
write-ups? e.g.
generic-labels, with-added-methods (RPG)
obsolete instances (dgb)
object creation (dam)
call-next-method (sk)
...
To be included in misc decisions file???
1.
...
∂14-Sep-87 2058 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 20:58:01 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233805; Mon 14-Sep-87 23:29:36 EDT
Date: Mon, 14 Sep 87 23:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Agenda for September meeting
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-164235-3253@Xerox>
Message-ID: <870914232936.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 16:42 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Discuss written proposals on major areas, circulated over the
network before the meeting and brought to the meeting in hardcopy.
A number of proposals have appeared over the network. How should they
appear in hardcopy. Do you intend to extract what you think are the
current proposals, or should we have distributed resposnsibility. Seems
like the latter is fairer, but we ought to have a list of the expected
proposals.
It will have to be distributed responsibility. Due to other commitments
I will not be able to do any significant amount of additional work to
prepare for the meeting. I don't think I will even be able to send out
a substantially revised version of the miscellaneous issues and
decisions file. I'd like each person who has proposed something to
bring at least one hardcopy of their proposal (I assume we can get things
copied at PARC). I'll bring hardcopies of things I have proposed and of
all the mail that I had thought was worth saving.
Do you have a list of such proposals that need separate write-ups?
Here's the list I made earlier today of issues that were discussed in the
mail since the last meeting, excluding very small issues. This covers
about 85 messages. Next to each one I put names of people who I noticed
having enough to say to count as a proposal. I may have missed some people.
Large issues are listed first, but otherwise there is no particular order.
Object Creation (Moon, possibly Gregor)
Class Redefinition (Bobrow, Moon, Dussud)
Class and Generic Function Naming (everybody?)
Local Generics, Methods (RPG)
Class Precedence (Moon, possibly RPG, possibly Kempf)
Trace (Kempf)
&key lambda-list congruence (Bobrow, Moon)
Short form of define-method-combination (Moon, Bobrow)
call-next-method with arguments (SKeene)
call-next-method closure extent (RPG)
Defmethod syntax for methods on individuals (Moon)
Virtual slots for with-slots ((Lanning))
Uninitialized Slots (Bobrow)
∂14-Sep-87 2129 Bobrow.pa@Xerox.COM Re: Names to Objects and Compiler-environment
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 21:29:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 17:17:19 PDT
Date: 14 Sep 87 17:17 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Names to Objects and Compiler-environment
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Wed, 26 Aug 87
11:28:22 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net,
common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870914-171719-3304@Xerox>
After reading the messages sent, I think that only the following very
simple name to object mapping interface should be supported.In general,
there must be (effectively) different objects in the different
environments, since objects in a compiler environment canot be allowed
to interact with the runtime objects; optimizations that minimize
copying should be invisible to the user. With this the other
generic-functions that Patrick suggested should be extended can be left
as they are.
Name To Object Generic Functions.
symbol-class symbol &optional environment
==> class or NIL
symbol-function symbol &optional environment ****
==> function or NIL
symbol-setf-function symbol &optional environment
==> function or NIL
**** Change to Common Lisp -- We should argue for it.
The generic-functions above all support setf forms:
(setf (symbol-class symbol &optional environment) class)
==> class
(setf (symbol-function symbol &optional environment) function)
==> function
(setf (symbol-setf-function symbol &optional environment) function)
==> function
If the value argument for any of these forms is NIL, then this is
equivalent to the corresponding CMAKUNBOUND, or FMAKUNBOUND ****
**** Change to Common Lisp -- We should argue for it.
For the Object to Name mapping, CLOS should provide the generic
functions:
class-name class
==> symbol
function-name function
==> symbol
These return a symbol. The return value is only considered a hint.
There is no guarantee that a symbol returned is a name for the class
(function), or if NIL is returned, the class or function does not have a
name.
∂15-Sep-87 0923 RPG Uninitialized Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
If we use Moon's proposed behavior
``In July we decided that signalling an error here should
depend on the declared safety level. ''
the proper terminology, according to my not-as-yet-adopted terminology
for error situations, is that accessing an uninitialized slot should
signal an error.
I believe Danny's proposal has the difficult-to-justify property of
encouraging users to write code whose correct behavior depends on the
safety level used during compilation. That is, if we provide a
generic function that is invoked upon some erroneous but common situation,
users will pack useful code into the methods on that function.
Danny writes:
``Rather than signal an error directly, I propose that a
generic-function be called, dependent in the same way on safety
level.... Among other things, this allows an easy
implementation of default values in classes, a current feature
of Loops, Strobe and KEE.''
-rpg-
∂15-Sep-87 0935 RPG Proposals
To: common-lisp-object-system@SAIL.STANFORD.EDU
I will bring hardcopies of my proposals. I will clean them up considerably
beforehand, but you can get the drift from the mail.
-rpg-
∂15-Sep-87 1009 kempf%hplabsz@hplabs.HP.COM Re: Proposals
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 10:09:05 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 15 Sep 87 10:05:13 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 15 Sep 87 11:09:47 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Proposals
X-Mailer: mh6.5
In-Reply-To: Your message of 15 Sep 87 09:35:00 -0700.
Date: Tue, 15 Sep 87 11:09:43 MST
Message-Id: <12363.558724183@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
> I will bring hardcopies of my proposals. I will clean them up considerably
> beforehand, but you can get the drift from the mail.
I'll do the same.
jak
∂15-Sep-87 1356 Bobrow.pa@Xerox.COM Re: Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 13:56:16 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 87 13:55:06 PDT
Date: 15 Sep 87 13:55 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Uninitialized Slots
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 15 Sep 87
09:23 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870915-135506-4468@Xerox>
If we use Moon's proposed behavior
``In July we decided that signalling an error here
should depend on the declared safety level. ''
the proper terminology, according to my not-as-yet-adopted
terminology for error situations, is that accessing an
uninitialized slot should signal an error.
I believe Danny's proposal has the difficult-to-justify
property of encouraging users to write code whose correct behavior
depends on the safety level used during compilation. That is, if we
provide a generic function that is invoked upon some erroneous but
common situation, users will pack useful code into the methods on
that function.
Given this argument, I suggest we back off on the commitment that there
can be compilation of slot-access that depends on the declared safety
level for standard instances. I propose that for standard-class the
system should ALWAYS call slot-uninitialized if an uninitialized slot is
accessed. It should be easy to build a metaclass that can provide
more optimized access for production compilation.
∂15-Sep-87 1627 kempf%hplabsz@hplabs.HP.COM Re: Updating Obsolete Instances (and CHANGE-CLASS)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 16:26:27 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 15 Sep 87 16:22:07 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 15 Sep 87 17:26:39 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Updating Obsolete Instances (and CHANGE-CLASS)
X-Mailer: mh6.5
In-Reply-To: Your message of 11 Sep 87 11:48:00 -0700.
<870911-114845-18011@Xerox>
Date: Tue, 15 Sep 87 17:26:36 MST
Message-Id: <15740.558746796@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Looking at the semantic difficulties section on pg. 2-9 for
> CHANGE-CLASS
> I did not propose that this protocol for obsolete instances replace the
> CHANGE-CLASS protocol. I have always thought it a mistake to confound
> these two cases. For CHANGE-CLASS, both the classes involved are still
> current (not obsolete), and hence a CLASS-CHANGED method can be called.
>
> The difficulties with changing an instance inside a method seem
> to be eliminated, since, although the class changes, all methods
> applicable before the change are still applicable afterwards, since
> the class precedence list is only being shortened from the more
> specialized end.
> For CHANGE-CLASS, the user can change an instance of any class to any
> other (e.g. from a window to an automobile) and the only guaraneed
> intersection of the class precedence list is OBJECT.
I was under the impression that CHANGE-CLASS was primarily there for
updating of obsolete instances. Since this proposal decouples the two,
CHANGE-CLASS/CLASS-CHANGED as currently formulated seems to be even
weaker.
I believe that user defined coercions are probably a good idea, but that they
should be integrated with the Common Lisp COERCE function (CLtL, pg.
51-52) rather than through a new function. Considering the already full
agenda for this week's meeting, I hesitate to suggest that we discuss this
(though I will come with a written up proposal, in case we have time). Both
CHANGE-CLASS and CLASS-CHANGED can be replaced by making COERCE a
generic function. The "destructive in-place modification" property which
seems to be the reason for CLASS-CHANGED can simply be the default behavior
for COERCE when called with a CLOS object. Optionally, a flag parameter could
be included to control this behavior. In any event, the semantic difficulties
mentioned in the spec and the statement "the generic function
CLASS-CHANGED is not intended to be called by the programmer" at the
beginning of the CLASS-CHANGED description seem to indicate that something
more is needed on this.
jak
∂15-Sep-87 1916 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Another try on object creation
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 15 Sep 87 19:16:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 163152; Tue 15-Sep-87 21:55:00 EDT
Date: Tue, 15 Sep 87 21:54 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870903-141438-10242@Xerox>
Message-ID: <870915215412.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 3 Sep 87 14:14 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Why
do we need &method-key? Why not make the congruence rules for generic
functions be those Moon described for &method-key i.e. the acceptable
named arguments for a generic function are the union of the named
arguments of the methods, or &allow-other-keys. The one feature this
eliminates is the ability to define a generic function for which all
methods must have exactly the same named arguments. This seems a small
loss, and we gain by not having to add another lambda-keyword.
I tried this out in the version of the proposal that I will bring to the
meeting, and it seems to work out fairly well.
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
In 87-002, the answer was very simple: methods work the same as ordinary
functions in this respect, and whatever CLtL says happens, happens.
With the introduction of &method-key, that's still true when &method-key
is not used, but when &method-key is used, the situation cannot happen
because the generic-function-to-method dispatching mechanism is defined
to do the checking. With your proposal to make &key work like
&method-key, the situation you mention can never happen.
CLtL p.62 says named-argument name mismatch "is an error", so the
argument list validity checking in the generic-function-to-method
dispatching mechanism should conform to that and signal an error under
implementation-dependent control.
∂15-Sep-87 2006 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 15 Sep 87 20:06:06 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 163174; Tue 15-Sep-87 23:07:47 EDT
Date: Tue, 15 Sep 87 23:06 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870904-085641-11164@Xerox>
Message-ID: <870915230654.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 4 Sep 87 08:56 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
To obtain a special version of print with added methods, one uses
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
#'print)
and passes the returned generic function as an argument. Note that
since the generic function is copied on entry, this specialized print is
not affected by later global changes to the print generic function.
This actually brings up an interesting point. PRINT is not a generic
function, PRINT-OBJECT is. If you change this example to specify
#'print-object instead of #'print, you realize that this is fairly
useless. The documentation of print-object says that the user is not
supposed to call it; it is called automatically by the system functions
such as PRINT, WRITE, and ~S. Making a copy of print-object with some
new methods is fairly useless, since there is no way to get the system
functions to call it. This is simply one instance of a general problem
with interfaces.
I don't think any mechanism that isn't essentially equivalent to dynamic
binding of function definitions will solve this problem. I'm not convinced
that CLOS actually needs to solve this problem though.
This point is somewhat off the main track of the anonymous generic function
proposal, and I do not consider it an argument against that proposal.
∂20-Sep-87 1904 Gregor.pa@Xerox.COM fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Sep 87 19:04:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 20 SEP 87 19:03:42 PDT
Date: 20 Sep 87 19:03 PDT
From: Gregor.pa@Xerox.COM
Subject: fixing our problems with setf
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870920-190342-9834@Xerox>
Unless we can get setf 'fixed' in the entire language, I propose that we
solve our problems with setf by eliminating all the setf features from
CLOS (except automatically generated writer methods). That means get
rid of the ability to say (setf <foo>) to defmethod, symbol-function,
generic-function-labels, generic-flet and the others.
My belief is that we are geting into trouble because we are confusing
(generic) function naming with defining setf macros. This gets us
screwed because setf is a macro in yet another namespace and doesn't
interact real well with our stuff.
Put another way, there isn't (right now) anything called defun-setf. If
you want to do that you have to do (something like):
(defsetf foo |setf FOO|)
(defun |setf FOO| (x new-value) ...)
Given that, I don't see whats so wrong with having to do:
(defsetf bar |setf BAR|)
(defmethod |setf BAR| ((x boat) new-value) ..)
∂21-Sep-87 0911 Bobrow.pa@Xerox.COM Re: fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 09:11:32 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 09:10:49 PDT
Date: 21 Sep 87 09:10 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: fixing our problems with setf
In-reply-to: Gregor.pa's message of 20 Sep 87 19:03 PDT
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870921-091049-10309@Xerox>
Unless we can get setf 'fixed' in the entire language, I
propose that we solve our problems with setf by eliminating all the
setf features from CLOS (except automatically generated writer
methods). That means get rid of the ability to say (setf <foo>) to
defmethod, symbol-function, generic-function-labels, generic-flet
and the others.
I also found our discussion last week of setf very uncomfortable, since
it doesn't work in the same way in the rest of Common Lisp. In
particular, the contrast between
(defmethod (setf foo) (a b) (c) ...)
which is legal (note -- no specializers)
and
(defun (setf foo) (a b) (c) ...)
which is unfortunately nonsense. I was also struck by the lack of a
local version of setf.
So much as I hate to agree with Gregor, I think we should follow changes
to Common Lisp with respect to setf, not lead it. I would hope that
someone would ask the cleanup committee to consider this issue.
danny
∂21-Sep-87 1109 RPG Issues on Dynamic Extent for CALL-NEXT-METHOD
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Here is a summary of the issues that Danny and I discussed with
regard to the extent of CALL-NEXT-METHOD last thursday and Friday.
The basic question is whether CALL-NEXT-METHOD ought to have dynamic
or indefinite extent. We have already agreed that it has lexical scope.
The crux of the matter is whether one can return a closure that
invokes CALL-NEXT-METHOD and thereby cause control to pass back
into the generic function.
In this discussion, all reference to Common Lisp code is to code written
without the use of macros.
Consider a generic function, GF, in which some number of methods are
defined. Suppose that one of them looks like this:
(defmethod GF (...) ... (throw C #(lambda () (call-next-method)))...)
and that all of them but the default method invokes CALL-NEXT-METHOD,
the intention being that all of the methods get run in inside-out order.
If C is later invoked, do we intend the cascade of method invocations
in inside-out order to continue where it left off?
Argument 1, in favor of indefinite extent.
The methods as defined within GF are like LABELS functions, and CALL-NEXT-METHOD
is analogous to calling one of these LABELS functions from inside another.
If we use CALL-NEXT-METHOD to define some internal control structure in
which the methods are individual parts of the control structure, then this
is no different from defining a similar control structure using local
functions.
Argument 2 (rebuttal to 1), in favor of dynamic extent.
A generic function is a black box once defined and invoked, and it
does not make good sense to be able to suspend execution of a generic
function at a method boundary with the possibility of proceeding that
execution later. Imagine doing this while performing a method combination.
Argument 3 (rebuttal to 2), in favor of indefinite extent.
You are free to do that with a tangled web of LABELS functions, so what's
the difference?
Argument 4 (answer to 3), in favor of dynamic extent.
When you capture a labels environment, you do not capture any hidden state
as you do with CALL-NEXT-METHOD. With function invocation you can either
see directly the function to be called [(foo 1 2 3) calls foo] or else you
can see the variable whose value is the function to be called [(funcall
*foo* 1 2 3) calls the value of *foo*]. CALL-NEXT-METHOD contains a hidden
`list' of methods left to be invoked. Common Lisp provides for no capture of
hidden state, so why do it here?
Argument 5, (rebuttal to 4), in favor of indefinite extent.
The hidden state in CALL-NEXT-METHOD is no different from the hidden
state of the function cell or the variable that controls which
function will be called.
Argument 6, in favor of dynamic extent.
Besides, your reduction of methods to LABELS functions has explanatory
power but no predictive power in this case. That is, we cannot rely
on reducibility as an accurate reflection of semantics.
Here is an example:
(defun even-odd (n)
(let ((odds 0)(evens 0))
(tagbody
l1 (when (< n 1) (return-from even-odd (values evens odds)))
l2 (if (evenp n) (go l3)(go l4))
l3 (incf evens) (go l5)
l4 (incf odds) (go l5)
l5 (decf n) (go l1))))
This behavior can be reduced to this:
(defun even-odd (n)
(let ((evens 0)(odds 0))
(labels ((l1 ()
(block even-odd
(when (< n 1) (return-from even-odd (values evens odds)))
(l2)))
(l2 ()
(block even-odd
(if (evenp n) (l3)(l4))))
(l3 ()
(block even-odd
(incf evens) (l5)))
(l4 ()
(block even-odd
(incf odds) (l5)))
(l5 ()
(block even-odd
(decf n) (l1))))
(l1))))
This might explain TAGBODY and GO in this case, but we cannot
take this sort of reduction to be an equivalence, because we can
now alter the second definition in such a way that the mapping back to
TAGBODY and GO is not valid:
Change the definition of L3 to:
(l3 ()
(block even-odd
(incf evens)
(when (= n 20)
(return-from even-odd #'(lambda () (l5))))
(l5)))
If we do
(even-odd 100)
we get a closure, and if we invoke it the computation continues
and returns 50, 50.
Now let's change the TAGBODY and GO definition the same way:
l3 (incf evens)
(when (= n 20) #'(lambda () (go l5)))
(go l5)
When we do (even-odd 100), we get a closure, but invoking it
causes a runtime error to be signaled.
Had we chosen to define TAGBODY and GO within Common Lisp to
be equivalent to a LABELS form, then the reduction would have
predictive power. Therefore, assuming that the reduction is
valid simply begs the question.
Argument 7 (rebuttal to 6), in favor of indefinite extent.
What are you talking about!! That sounds bogus to me. Methods are more
like functions than they are like TAGBODY labels, and CALL-NEXT-METHOD is
like a function call, because you can return from it.
Argument 8 (summary), in favor of dynamic extent.
The reason that TAGBODY and GO is not reduced to LABELS is to allow
implementors to do a better job with GO than with function call. Maybe
there's a fast way to do CALL-NEXT-METHOD if there isn't a dubious feature
to implement, especially when hardly anyone will use that feature.
Argument 9 (summary), in favor of indefinite extent.
Let's make the whole thing simpler by not instituting this funny
dynamic extent constraint that no real programmers understand
anyway.
[rpg: I would only care if there were some performance issue,
as in Argument 8, but I doubt there is, and I doubt it's important.]
-rpg-
∂21-Sep-87 1121 RPG New Trivial Issue: Implicit Blocks in Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
Common Lisp defines DEFUN to put an implicit block around the
body of the function.
(defun foo (...) <body>) => (defun foo (...)(block foo <body>))
Does DEFMETHOD do the same thing?
(defmethod foo (...) <body>) => (defmethod foo (...)(block foo <body>))?
Suppose there is a generic function named FOO with some methods.
If there is an implicit block named FOO, then the form
(return-from foo <value>)
will return from the method. If the invocation of the method was
from CALL-NEXT-METHOD, control returns to the point-of-call.
Suppose we really wanted to return from the generic function FOO?
The only way would be to put a CATCH around the invocation of it,
and therefore a programmer could not exit a generic function from within
a method.
Alternative 1. DEFMETHOD includes an implicit block of the same name as
the method, and the programmer cannot exit a generic function summarily.
Alternative 2. Generic functions have an implicit block if the same name
around them, and the programmer has to explicitly include a block
name in his DEFMETHOD if that's what he wants.
Alternative 3. Invent some new way of exiting.
E.g. ...(return-from-generic-function ...)...
Alternative 1 might shaft some people, and certainly it makes a
raft of code harder to write. But how often does someone want to
summarily exit a generic function?
Alternative 2 probably is implemented with something like a CATCH, and so
it slows down generic function invocation a little.
Alternative 3 adds some hair and also has implementation implications.
-rpg-
∂21-Sep-87 1159 Moon@STONY-BROOK.SCRC.Symbolics.COM New Trivial Issue: Implicit Blocks in Methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Sep 87 11:59:23 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 237734; Mon 21-Sep-87 15:01:03 EDT
Date: Mon, 21 Sep 87 15:00 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: New Trivial Issue: Implicit Blocks in Methods
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 21 Sep 87 14:21 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870921150018.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 21 Sep 87 1121 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Common Lisp defines DEFUN to put an implicit block around the
body of the function.
(defun foo (...) <body>) => (defun foo (...)(block foo <body>))
Does DEFMETHOD do the same thing?
(defmethod foo (...) <body>) => (defmethod foo (...)(block foo <body>))?
This is what we do in Flavors, and people seem to find it useful.
Suppose there is a generic function named FOO with some methods.
If there is an implicit block named FOO, then the form
(return-from foo <value>)
will return from the method. If the invocation of the method was
from CALL-NEXT-METHOD, control returns to the point-of-call.
Suppose we really wanted to return from the generic function FOO?
The only way would be to put a CATCH around the invocation of it,
and therefore a programmer could not exit a generic function from within
a method.
That's right. Typically the CATCH would be in a :AROUND method. Sometimes
people define special method-combination types that establish this sort of
control structure, also. (define-method-combination or) is about the simplest
way to do it.
Alternative 1. DEFMETHOD includes an implicit block of the same name as
the method, and the programmer cannot exit a generic function summarily.
Alternative 1 is what Flavors does now.
Alternative 2. Generic functions have an implicit block if the same name
around them, and the programmer has to explicitly include a block
name in his DEFMETHOD if that's what he wants.
I don't think alternative 2 can work within the philosophy of Common
Lisp, because a method is not lexically inside of its generic function.
Alternative 3. Invent some new way of exiting.
E.g. ...(return-from-generic-function ...)...
THROW suffices.
∂21-Sep-87 1231 Bobrow.pa@Xerox.COM Re: New Trivial Issue: Implicit Blocks in Methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 12:31:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 12:00:20 PDT
Date: 21 Sep 87 11:57 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: New Trivial Issue: Implicit Blocks in Methods
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Sep 87
11:21 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870921-120020-10687@Xerox>
Alternative 1. DEFMETHOD includes an implicit block of the same
name as the method, and the programmer cannot exit a generic
function summarily.
Alternative 2. Generic functions have an implicit block if the
same name around them, and the programmer has to explicitly include
a block name in his DEFMETHOD if that's what he wants.
Alternative 3. Invent some new way of exiting. E.g.
...(return-from-generic-function ...)...
How about:
Alternative 4. Named generic functions have an implicit block around
them with a constructed name e.g. for FOO:
|generic-function FOO|
This need not be coded in the generic-function unless at least one of
the methods uses the feature.
If this is not good, then I vote for 1 on the basis of Dick's last
comment:
But how often does someone want to summarily exit a generic
function?
∂21-Sep-87 1232 Bobrow.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 12:31:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 12:00:22 PDT
Date: 21 Sep 87 11:59 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Sep 87
11:09 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870921-120022-10688@Xerox>
I agree with Dick's summary of the argument we had. I also think the
dominating argument is:
Argument 9 (summary), in favor of indefinite extent.
Let's make the whole thing simpler by not instituting this
funny dynamic extent constraint that no real programmers understand
anyway.
danny
∂21-Sep-87 1246 Masinter.pa@Xerox.COM Re: fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 12:46:13 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 12:38:36 PDT
Date: 21 Sep 87 12:38 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: fixing our problems with setf
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 21 Sep 87 09:10 PDT
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870921-123836-10807@Xerox>
I urge you to lead the cleanup committee rather than follow it in this
area, i.e., go ahead with your proposal of how SETF within CLOS ought to
work, and we can construct a cleanup for the rest of CL as well.
You can annotate the section with a footnote to the effect that the
reasonable of this section is conditional on a concurrent change to the
general way in which CL handles SETF, which is in preparation.
I'm afraid of a deadlock situation, where CLOS and CL-Cleanup are
waiting for each other; I don't think it will do anyone any good.
I don't see any harm in your assuming some changes to the rest of CL to
accomodate CLOS when the reasons are justified -- as I think they are in
this case.
∂21-Sep-87 1312 Gregor.pa@Xerox.COM Re: fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 13:12:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 13:13:16 PDT
Date: 21 Sep 87 13:13 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: fixing our problems with setf
In-reply-to: Masinter.pa's message of 21 Sep 87 12:38 PDT
To: Masinter.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870921-131316-10876@Xerox>
My proposal for how to cleanup setf in common lisp is compatible with
the suggestion I am making for CLOS.
I will try to send a 'test balloon' message to the cleanup committee
about this soon.
∂21-Sep-87 1334 Moon@STONY-BROOK.SCRC.Symbolics.COM fixing our problems with setf
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 21 Sep 87 13:34:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 237933; Mon 21-Sep-87 16:35:56 EDT
Date: Mon, 21 Sep 87 16:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: fixing our problems with setf
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870920-190342-9834@Xerox>
Message-ID: <870921163510.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 20 Sep 87 19:03 PDT
From: Gregor.pa@Xerox.COM
Unless we can get setf 'fixed' in the entire language, I propose that we
solve our problems with setf by eliminating all the setf features from
CLOS (except automatically generated writer methods). That means get
rid of the ability to say (setf <foo>) to defmethod, symbol-function,
generic-function-labels, generic-flet and the others.
I'd hate to see unmotivated (from the user point of view) incompatibility
between automatically generated writer methods and methods the user could
write herself. That just makes the language seem more complicated.
My belief is that we are geting into trouble because we are confusing
(generic) function naming with defining setf macros. This gets us
screwed because setf is a macro in yet another namespace and doesn't
interact real well with our stuff.
I think this is a fair summary of the problem. I also don't think
fixing setf in the entire language is difficult. The following example
is taken directly from a Symbolics Common Lisp Listener:
(defun testcase (x) (cadr x))
TESTCASE
(defun (setf testcase) (x new-value) (setf (cadr x) new-value))
(SETF TESTCASE)
(mexp)
Type End to stop expanding forms
Macro form → (setf (testcase list) 105) →
(FUNCALL #'(SETF TESTCASE) LIST 105)
Macro form →
NIL
(setq list '(1 2 3))
(1 2 3)
(testcase list)
2
(setf (testcase list) 5)
5
list
(1 5 3)
The basic idea that is going on here is that the mere existence of a function
named (setf foo) is sufficient to tell setf all it needs to know about foo.
In the meeting last week, we were talking about defining this function and
calling defsetf as two separate acts, and I think that may be where the
trouble arose. If we simply say that setf is extended with this new mechanism
for setf-functions, which is in addition to the setf-macros defined by
defsetf and define-setf-method, then everything should work. The only
complexity is defining what happens if someone is unfortunate enough to
try to define both a setf-function and a setf-macro for the same function.
The problem here is that this once again raises the spectre of function-specs.
Perhaps we should just press forward with the assumption that everyone who
hated function-specs in the past has forgotten about that.
Gregor: Perhaps you can use this as raw material for a cleanup proposal?
Do you need any help on that?
∂21-Sep-87 1555 Gregor.pa@Xerox.COM Re: New Trivial Issue: Implicit Blocks in Methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 15:55:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 15:55:19 PDT
Date: 21 Sep 87 15:55 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: New Trivial Issue: Implicit Blocks in Methods
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 21 Sep 87 11:57 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870921-155519-11188@Xerox>
An implicit block around the body of the method is what PCL does now. I
believe this is what we should do in CLOS. This should go in the
section which describes the defmethod macro.
∂21-Sep-87 1611 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: New Trivial Issue: Implicit Blocks in Methods
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 21 Sep 87 16:11:36 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa21445; 21 Sep 87 18:01 EDT
Received: from ti-csl by RELAY.CS.NET id ah22745; 21 Sep 87 17:46 EDT
Received: from Jenner by tilde id AA20307; Mon, 21 Sep 87 16:06:51 CDT
Message-Id: <2768245790-4638470@Jenner>
Date: Mon, 21 Sep 87 16:09:50 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: New Trivial Issue: Implicit Blocks in Methods
In-Reply-To: Msg of 21 Sep 87 1121 PDT from Dick Gabriel <RPG@sail.stanford.edu>
Date: 21 Sep 87 1121 PDT
From: Dick Gabriel <RPG@sail.stanford.edu>
Subject: New Trivial Issue: Implicit Blocks in Methods
Common Lisp defines DEFUN to put an implicit block around the
body of the function.
(defun foo (...) <body>) => (defun foo (...)(block foo <body>))
Does DEFMETHOD do the same thing?
(defmethod foo (...) <body>) => (defmethod foo (...)(block foo <body>))?
Suppose there is a generic function named FOO with some methods.
If there is an implicit block named FOO, then the form
(return-from foo <value>)
will return from the method. If the invocation of the method was
from CALL-NEXT-METHOD, control returns to the point-of-call.
Suppose we really wanted to return from the generic function FOO?
The only way would be to put a CATCH around the invocation of it,
and therefore a programmer could not exit a generic function from within
a method.
Alternative 1. DEFMETHOD includes an implicit block of the same name as
the method, and the programmer cannot exit a generic function summarily.
It sounds like a good idea.
Alternative 2. Generic functions have an implicit block if the same name
around them, and the programmer has to explicitly include a block
name in his DEFMETHOD if that's what he wants.
This would mean that violate the scoping rule of a block name (it is
lexical).
Alternative 3. Invent some new way of exiting.
E.g. ...(return-from-generic-function ...)...
I think that this feature won't be used enough to justify the trouble.
People will program it using catch and throw.
Patrick.
∂21-Sep-87 1615 Masinter.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 21 Sep 87 16:15:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 21 SEP 87 16:10:30 PDT
Date: 21 Sep 87 16:10 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Sep 87
11:09 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870921-161030-11218@Xerox>
I prefer dynamic extent.
a) I can easily imagine implementations of CLOS where there is a
performance penalty for indefinite extent.
b) I disbelieve the presumption of Argument 9 (the last in your
message), namely "Let's make the whole thing simpler by not instituting
this funny
dynamic extent constraint that no real programmers understand
anyway.")
I believe most real programmers understand the dynamic extent of tags
and block names.
c) I believe that it will be easier to support environmental features to
prevent unintended interactions between changes to the class hierarchy
and CALL-NEXT-METHOD if CALL-NEXT-METHOD has dynamic, rather than
indefinite, extent.
d) The only objects in CL with indefinite extent are "first class"
objects to which variables can be bound and which can be returned as
values. Functions created by LABELS have indefinite extent, but they can
be named and returned. "The next method" has no such
value-representation, and so the analogy to LABELS does not hold. (The
correlation between whether a value is "first class" and its extent
seems to hold across Common Lisp.)
∂21-Sep-87 2135 RPG Issues on Dynamic Extent for CALL-NEXT-METHOD
To: common-lisp-object-system@SAIL.STANFORD.EDU
Today I talked to Guy Steele on the phone, and I told him
about generic functions, methods, and call-next-method without
expressing any opinions about them. When I asked what extent
call-next-method should have, he thought for a while and stated
`dynamic.' When I asked why, he gave argument 4, which talks about
the capture of hidden state.
-rpg-
∂22-Sep-87 1417 Moon@MEAD.SCRC.Symbolics.COM SLOT-BOUNDP or SLOT-BOUND-P
Received: from [128.81.41.234] by SAIL.STANFORD.EDU with TCP; 22 Sep 87 14:17:35 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by MEAD.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 94641; Tue 22-Sep-87 16:53:37 EDT
Date: Tue, 22 Sep 87 16:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: SLOT-BOUNDP or SLOT-BOUND-P
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870922165333.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I'm transcribing my notes from last week's meeting now.
At the meeting, we decided that the correct spelling, according to CLtL,
was SLOT-BOUND-P. I've just read CLtL p.71 and I believe this is
incorrect. It says "If the name of a predicate is formed by adding a
prefixing qualifier to the front of an existing predicate name, the two
names are joined with a hyphen and the presence or absence of a hyphen
before the final p is not changed."
Therefore, I'm going to use the spelling SLOT-BOUNDP. Please let me
know if you disagree.
∂22-Sep-87 1802 Bobrow.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Sep 87 18:02:10 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 SEP 87 18:02:39 PDT
Date: 22 Sep 87 18:02 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
In-reply-to: Masinter.pa's message of 21 Sep 87 16:10 PDT
To: Masinter.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870922-180239-12959@Xerox>
Given that Masinter, Steele and Gabriel seem to agree, I don't care
enough to fight on this issue. So call it one abstention in favor of
Dynamic Extent.
danny
∂22-Sep-87 2004 Moon@STONY-BROOK.SCRC.Symbolics.COM September version of object-creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Sep 87 20:04:13 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 239305; Tue 22-Sep-87 23:05:06 EDT
Date: Tue, 22 Sep 87 23:04 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: September version of object-creation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870922230450.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
The following has been updated from my notes from last week's meeting.
As far as I know this has all been approved except for some slight
fuzziness at the meta-object level, so if you disagree, speak now.
The next step will be to convert this from proposal format to a
format appropriate to go into the Concepts and Functions chapters
of the CLOS specification.
-foo- means the word foo in italics. FOO means the word foo in boldface.
CONCEPTS TO BE ADDED TO 87-002
-named argument-. We use the term "named argument" instead of "keyword
argument" (as in CLtL) for &key arguments, because CL-Cleanup issue
KEYWORD-ARGUMENT-NAME-PACKAGE has stated that the names of &key arguments
do not have to be keyword symbols. This proposal assumes named arguments
to methods work as described in the accompanying lambda-list congruence
proposal.
-named argument name-. The symbol that identifies a named argument in
an argument list. This is typically a keyword, but is not required to be.
The named-argument name should not be confused with the variable name
of the parameter variable. These two symbols typically have the same
name and are typically in different packages, but that is not required.
-initarg-. An initarg (initialization argument) is a named argument that can
be used to control object creation and initialization. The &key arguments to
MAKE-INSTANCE are initargs. It is often convenient to use keyword symbols to
name initargs, but the name of an initarg can be any symbol, including NIL.
-initarg list-. An initarg list (initialization argument list) is a list
of alternating initarg names and values. Its structure is identical to a
property list and also identical to an &key argument list. As in those
lists, if an initarg name appears more than once in an initarg list, the
leftmost occurrence supplies the value and the remaining occurrences are
ignored. The arguments to MAKE-INSTANCE, after the first, are an initarg
list. As in an &key argument list, :ALLOW-OTHER-KEYS can appear in an
initarg list, and if its value is non-NIL, error-checking of initarg names
is disabled.
-slot-filling initarg-. An initarg associated with a slot. If the initarg
has a value in the initarg list, the value is stored into the slot of the
newly-created object, overriding any initform associated with the slot. A
single initarg can fill more than one slot. A slot-filling initarg that
fills a shared slot stores its value into the shared slot, replacing any
previous value.
-method-implemented initarg-. An initarg associated with a method. When
an object is created, the method is called with the initarg's value as an
argument and the method uses the value in any way it likes. If the initarg
has no value in the initarg list, the method's lambda-list supplies a
default value. A single initarg can be implemented by more than one
method. An initarg can be both slot-filling and method-implemented.
CHANGES TO 87-002 FEATURES
DEFCLASS gets a new :INITARG slot option, which is followed by a symbol.
The symbol becomes the name of a slot-filling initarg for this class.
This slot option can appear any number of times.
DEFCLASS gets a new :DEFAULT-INITARGS option, which is followed by an initarg
list. Each value in this list is a form that is evaluated by MAKE-INSTANCE if
the initarg does not already have a value in the initarg list. The initarg
name and the form's value are added to the end of the initarg list. The form
is evaluated in the lexical environment in which the DEFCLASS form was
evaluated. The appearance of a symbol in a :DEFAULT-INITARGS option does not
make that symbol a valid initarg name for the class.
Method-implemented initargs are defined simply by defining a method for
INITIALIZE-INSTANCE or ALLOCATE-INSTANCE; each named-parameter name in the
method's lambda-list becomes a method-implemented initarg for all classes for
which this method is applicable.
Initarg inheritance: The effective set of slot-filling initargs for a class C
is the union of the slot-filling initargs defined by C and its superclasses.
The effective set of method-implemented initargs for a class C is determined
by method inheritance.
Default-initargs inheritance: The set of initargs of C that have default value
forms is determined by the union of the :DEFAULT-INITARGS options of C and its
superclasses. When more than one class in the CPL specifies a default value
form for a given initarg, only the form specified by the earliest such class in
the CPL is used.
Rules when initargs are duplicated in various ways:
The :INITARG slot-option may be specified more than once for a given slot.
A single initarg can initialize more than one slot if the same initarg name
appears in more than one :INITARG slot-option.
It is valid for a given initarg name to be defined more than once as a
slot-filling initarg, as a method-implemented initarg, or both.
If two initargs that initialize the same slot, with the same or different
names, are given in the arguments to MAKE-INSTANCE, the leftmost of these
initargs in the initarg list prevails.
If there are two different initargs that initialize the same slot, and one
was given explicitly in the arguments to MAKE-INSTANCE while the other was
defaulted via :DEFAULT-INITARGS, the explicit one prevails.
If two different initargs that initialize the same slot have default values,
the initarg that appears in a :DEFAULT-INITARGS slot-option in the most
specific class prevails, or if they appeared in the same class, the one whose
mention in :DEFAULT-INITARGS is leftmost in the DEFCLASS form prevails.
Defaulted initargs are appended to the end of the initarg list in this order.
If a slot has both an :INITFORM and an :INITARG slot-option, and the
slot-filling initarg is defaulted via :DEFAULT-INITARGS, the initform is not
used and is not evaluated.
An illustrative example of the above rules:
(defclass a () ((x :initarg a)))
(defclass b (a) ((x :initarg b))
(:default-initargs a 1 b 2))
FORM INITARG LIST CONTENTS OF X SLOT
(make-instance 'b) (a 1 b 2) 1
(make-instance 'b 'a 3) (a 3 b 2) 3
(make-instance 'b 'b 4) (b 4 a 1) 4
(make-instance 'b 'a 1 'a 2) (a 1 a 2 b 2) 1
NEW FUNCTIONS TO BE ADDED
In this section, I have only sketched each function, for the sake of brevity.
Full writeups can be constructed once the overall framework has been agreed
upon. Functions are in alphabetical order, in three sections at three protocol
levels. The breakdown between the second and third levels may be changed. By
coincidence, all functions listed except SLOT-BOUNDP and SLOT-MAKUNBOUND are
generic and expected to specialize on their first argument.
>>> Tools used for simple object-oriented programming:
(INITIALIZE-INSTANCE instance &key &allow-other-keys)
MAKE-INSTANCE calls this with the freshly-created instance, any initargs that
were supplied to MAKE-INSTANCE, and any defaulted initargs. Users define
methods for this to create method-implemented initargs. Typically,
user-defined methods are :AFTER methods, however that is not a requirement.
The primary method for INITIALIZE-INSTANCE is system-supplied and takes care
of the slot-filling initargs. For each slot (whether local or shared):
- if an initarg was specified or defaulted that fills that slot, its
value is stored into the slot.
- otherwise, if the slot is uninitialized and it has an initform, the
initform is evaluated and the result is stored into the slot.
- the duplicate-resolution rules mentioned earlier are obeyed.
An implementation is permitted to optimize initforms that neither produce nor
depend on side-effects, by evaluating them and storing them into slots before
running any INITIALIZE-INSTANCE methods, rather than handling them in the
primary INITIALIZE-INSTANCE method. This might be implemented by having the
ALLOCATE-INSTANCE method copy a prototype instance. This means that :BEFORE
and :AROUND methods for INITIALIZE-INSTANCE cannot rely on all the slots being
uninitialized at the beginning.
An implementation is permitted to optimize default value forms for slot-filling
initargs by not actually consing the complete initarg list, when the only
method that would see the complete list is the system-supplied primary method,
e.g. when no other methods use &REST. In this case default value forms can be
treated like initforms. This has no visible effects other than a performance
improvement.
(MAKE-INSTANCE class &key -initargs-...) => instance
Users call this function to create objects. Class can be either a class or
the name of a class. Meta-users can define new methods for MAKE-INSTANCE
to replace the object-creation protocol.
(SLOT-BOUNDP instance slot-name) => boolean
Allows writing INITIALIZE-INSTANCE :AFTER methods that only initialize slots if
they haven't been initialized already.
(SLOT-MAKUNBOUND instance slot-name) => NIL
Restores a slot to the uninitialized condition.
>>> Functions underlying the tools
(CLASS-ALL-INITARGS class) => list of initarg names, including inherited
ones. This is (REDUCE #'UNION (MAPCAR #'CLASS-DIRECT-INITARGS cpl)).
(CLASS-DIRECT-INITARGS class) => list of initarg names. This works by
computing the applicable methods for ALLOCATE-INSTANCE and for
INITIALIZE-INSTANCE and examining their arglists, and combining that
with the class's list of slot-filling initargs.
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
[Should there also be a way to reconstruct the form from
which default-value-function was generated?]
(CLASS-DIRECT-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
This reflects the :DEFAULT-INITARGS option.
(CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
This reflects the :INITARG slot-option.
(COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods
(METHOD-NAMED-PARAMETERS method) => list of symbols or &ALLOW-OTHER-KEYS
>>> Meta-object functions
(ALLOCATE-INSTANCE class &key &allow-other-keys) => instance
Meta-users can replace the system-supplied, implementation-dependent method for
this. Any named-arguments accepted by applicable ALLOCATE-INSTANCE methods
become valid initargs.
(CHECK-INITARGS class initarg-list)
Meta-users could replace the system-supplied method that implements the
normal rules for initarg validity.
(DEFAULT-INITARGS class initarg-list) => initarg-list
The system-supplied method implements the :DEFAULT-INITARGS class option
by appending initargs that do not appear in initarg-list to the end
of the returned list. The initarg-list supplied as an argument is not
modified. The order of initargs appended to the list is determined by
the duplicate-initarg rules listed earlier.
(FINALIZE-INHERITANCE class &key slots methods initargs)
This is called by the system at least once before a class is instantiated, and
is called again whenever anything relevant changes. System-supplied methods
for this conspire with methods for CHECK-INITARGS, etc., to make MAKE-INSTANCE
faster. Users with their own optimization needs can add methods for this
generic function that will precompute things based on inherited information,
and update the precomputed information whenever anything changes.
The :slots, :methods, and :initargs arguments are booleans that are true
when the specified type of inheritance needs to be recomputed.
PROCEDURAL DEFINITION OF MAKE-INSTANCE
MAKE-INSTANCE behaves as if it was defined as follows, except that certain
optimizations are permitted, as detailed below and in the description of
INITIALIZE-INSTANCE.
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
Optimization is possible, including inlining and constant-folding of method
lookup and method bodies, provided that the programming environment either
prohibits redefining these methods or updates everything when they are
redefined. A possible example implementation would be that MAKE-INSTANCE has
a separate method for every class, which is automatically written and compiled
by the system.
This optimization relies on the FINALIZE-INHERITANCE generic function and some
unpublished slots of STANDARD-CLASS.
Because of optimization, methods for the generic functions listed may not
actually be called on every call to MAKE-INSTANCE, or may not receive
exactly the arguments that would be expected. For example, CHECK-INITARGS
may actually be called before DEFAULT-INITARGS rather than after, if it has
already been determined that the default initargs will pass CHECK-INITARGS.
Additional explicit details of permissible optimization will need to be set
forth.
MEETING OF STATED DESIGN GOALS
Lexical proximity of concepts--the declaration of an initarg as valid,
the specification of what it does, and the default if it is not supplied
are all together, in a slot specifier or in a method lambda-list.
Simple ways to do simple things--slot-filling initargs don't require the
user to write any code. Method-implemented initargs work just like
ordinary function arguments as far as the user is concerned.
Minimal number of new languages--the only addition to Common Lisp is
a mildly complicated rule for how &KEY lambda-lists of methods do
validity checking.
Ability to do everything at some level--the underlying procedural level
is available. Functions to access all the direct and inherited
information are documented.
Underlying mechanism is exposed so user can use it for other things, rather
than abusing instance creation as the only way to access the mechanism--the
combination of &KEY, METHOD-NAMED-PARAMETERS, COMPUTE-APPLICABLE-METHODS, and
FINALIZE-INHERITANCE provides everything the user needs.
∂22-Sep-87 2008 Moon@STONY-BROOK.SCRC.Symbolics.COM Status of CLOS decisions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Sep 87 20:07:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 239307; Tue 22-Sep-87 23:08:07 EDT
Date: Tue, 22 Sep 87 23:07 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Status of CLOS decisions
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870922230752.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
The following has been updated from my notes from last week's
meeting. I apologize for the great length and uneven level of detail.
I believe that this accurately reflects the decisions made by the CLOS
working group, so if you find any discrepancies, or anything you disagree
with, please speak up now.
This file reflects Moon's understanding of the status of various CLOS issues,
concentrating on the more minor issues. The goal is to make sure that nothing
is overlooked, and especially to make sure that issues that have been brought up
and resolved are not forgotten before they get into the document. I've removed
most comments that were purely editorial comments on the document. I also
haven't tried to keep track of all the purely meta-object issues. I've edited
things to be as brief as possible.
All page references are to the 87-002 version of the CLOS document.
The file is divided into pages as follows:
0. This page of general outline
1. Documented holes in chapters 1 and 2 of 87-002
2. Things that have been already decided (but may not be in the document yet)
3. Issues with no apparent remaining disagreement
4. Small issues needing discussion
5. Issues whose status is unclear, maybe to be tabled
6. Things to do another day
7. Big issues needing discussion, each on its own page
==================================================
DOCUMENTED HOLES IN CHAPTERS 1 AND 2 OF 87-002
We publicly promised X3J13 that we would finish these holes and also have a new
draft of 87-003 by the next meeting (November).
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
Agreed in September, except for a few meta-object details.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
Document has been updated in draft.
Need Cleanup Committee proposals for fixes to the type system.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
This may not have been put into the document yet.
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
==================================================
THINGS THAT HAVE BEEN ALREADY DECIDED (BUT MAY NOT BE IN THE DOCUMENT YET)
27 May 87 call-next-method is allowed to take arguments, however it is an error
to give it arguments that would change the set of applicable methods. I think
we're saying this signals an error, and mentioning that in some simple cases the
lack of need for an error check can be proved at compile time, but in general a
run-time check is required. Specify precisely the type of error signalling.
Agreed in September. New writeup approved.
10 June 87 The document has been updated with a discussion of how the standard
type classes are organized.
8/9/87 Gregor promised to draw a picture.
2-16 (slot-name form) is not allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
we have to document explicitly that it is not allowed.
The decision to reject (slot-name form) was made at the July meeting.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
In September, we switched to a different idea, requiring reading of an
uninitialized slot to call the slot-uninitialized generic function,
regardless of safety level. The default method signals an error.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated. DEFINE-METHOD-COMBINATION returns the name.
p2-39 Arguments: "list of t's" should be replaced by "list whose elements are
the class named t" since get-method only takes specializers, not names of
specializers.
Agreed.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-54 in the Amendments: Clarify that because class names and classes are
type-specifiers, they can be validly be used in THE special forms and in TYPE
declarations. We forgot this when we clarified that class objects can be used
with TYPEP and SUBTYPEP.
July: agreed
DEFGENERIC-OPTIONS acquired a :METHOD option, whose syntax is the syntax of
DEFMETHOD without the generic-function name, at the September meeting.
Consequently, DEFGENERIC-OPTIONS has been renamed to DEFGENERIC. It is to
be explained in terms of a call to ENSURE-GENERIC-FUNCTION followed by
zero or more invocations of DEFMETHOD.
DEFGENERIC-OPTIONS-SETF and DEFMETHOD-SETF were removed in September.
Instead, DEFMETHOD takes on the syntax of DEFMETHOD-SETF, with two
lambda-lists, when the generic-function name is a list whose car is SETF
and whose cadr is the reader-function-name. Thus we have a limited
function-spec facility where (SETF reader) is a writer-function-name.
DEFGENERIC works analogously. SYMBOL-FUNCTION, FBOUNDP, FMAKUNBOUND,
and ENSURE-GENERIC-FUNCTION will also accept these function-specs.
[This is conditional on figuring out how to fix SETF in Common Lisp]
GENERIC-FUNCTION is a new special form approved in September. Its subforms
are similar to those of DEFGENERIC, omitting the name and the SETF variant,
but it returns an anonymous generic-function object rather than defining a
named generic function.
GENERIC-LABELS and GENERIC-FLET are new special forms approved in
September. Their syntax resembles DEFGENERIC in exactly the way that the
syntax of LABELS and FLET resembles DEFUN.
[In the notes I have, the lambda-list is omitted, but that can't be
right since the :argument-precedence-order option depends on having
the lambda-list.]
WITH-ADDED-METHODS is a new special form approved in September. It is
similar to GENERIC-LABELS but also copies methods from another generic
function with the same name in an outer contour.
WITH-SLOTS was thoroughly revised in September. It now lists explicitly
the slots to be made accessible and the pseudo-variable-names by which they
will be accessible. It no longer calls accessor functions. It no longer
takes any keyword options. It no longer accesses multiple instances in
a single level of nesting. The calls to SLOT-VALUE produced by expansion
of WITH-SLOTS can still get specially optimized in some contexts such
as bodies of methods.
SYMBOL-MACROLET was added in September. It is the basic mechanism that
is used to implement WITH-SLOTS as well as user-written macros for some
of the other things that the old WITH-SLOTS did and for "virtual slots."
It allows substitution of forms for pseudo-variable-names within a
lexical scope.
The :ACCESSOR-PREFIX and :READER-PREFIX options to DEFCLASS, and the
:PREFIX option to WITH-SLOTS, were removed in September.
The function NEXT-METHODS was added in September. It is scoped the same as
CALL-NEXT-METHOD, takes no arguments, and returns a list of method objects,
of which the first is the one that CALL-NEXT-METHOD calls. The effect of
modifying the list is undefined.
The function ENSURE-GENERIC-FUNCTION was added in September. It takes a
name, which is a symbol or a SETF function-spec, and named-arguments
corresponding to all the features of DEFGENERIC other than :METHOD, and
does what DEFGENERIC does.
SYMBOL-CLASS is the function that maps from a symbol to the class it
names. It can be SETF'ed. The new functions CBOUNDP and CMAKUNBOUND
were added to complement this. SETF of SYMBOL-CLASS is undefined for
certain built-in class names (to be defined).
SYMBOL-FUNCTION, FBOUNDP, FMAKUNBOUND, ENSURE-GENERIC-FUNCTION,
SYMBOL-CLASS, CBOUNDP, and CMAKUNBOUND take an optional environment
argument, which controls name-to-object mapping. These environments
are the same as the &environment argument to macro expanders, and
are typically used to distinguish between compile-time and run-time
environments. The detailed semantics of these environments will be
defined at the meta-class and implementation levels.
The TRACE-EXECUTION generic function was approved for addition at the
meta-object level in September. It is the underlying function behind
TRACE but provides some additional features.
The EXACT-TYPE declaration was approved in September. It is similar
to the TYPE declaration, but does not permit the value to be a subtype.
This is most useful when the type is a class.
Some simplifications to the short-form of DEFINE-METHOD-COMBINATION were
approved in September; the method qualifier is no longer optional and no
longer a keyword symbol.
NO-APPLICABLE-METHOD is a generic function, added in September, that
is called when a generic function is called but no applicable methods
exist. The arguments are the original generic function, the first
argument, and then all of the arguments (including the first); the
lambda-list indicates two required parameters and an &rest parameter.
SLOT-EXISTS-P was added in September; it takes an object and a slot-name
and returns a Boolean.
The following functions found in 87-002 will be removed or renamed:
Function Removed Replacement
class-named symbol-class
defgeneric-options defgeneric
defgeneric-options-setf defgeneric
defmethod-setf defmethod
get-setf-generic-function ensure-generic-function
make-generic-function make-instance
make-method make-instance
multiple-value-prog2 (none)
==================================================
ISSUES WITH NO APPARENT REMAINING DISAGREEMENT
1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Gregor says the metaclass protocol includes a predicate function that controls
whether the metaclass can be changed, which depends on whether the
representations differ and existing instances might not be transformable.
Some cross-reference to this should be added to the documentation of DEFCLASS.
1-15 to 1-22 Several errors in the formal description of class precedence and
method combination, pointed out by Jim Kempf on 4 August and 27 July, need to be
corrected. These are editorial changes only, that is, they make what the
document says conform to what I believe our intent to have been.
2-35 The argument order of the setf method ought to be documented here.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. It's important that this depends only on the two
lambda-lists, and not on any context such as the generic function object.
We still have defmethod-setf so that most users don't have to think about it
(only users making setf methods "directly").
[But in September, that was changed. Instead, defmethod takes on the syntax
of defmethod-setf, with two lambda-lists, when the generic-function name
is a list whose car is SETF.]
The rule, carefully worded so as to work in the face of implementations with
non-standard lambda-list-keywords, is that the setf-lambda-list is inserted
into the normal lambda-list immediately after the last parameter-specifier
that precedes &optional, &rest, &key, or &aux. This is implemented by the
following function (should it be standardized as part of CLOS?):
(defun combine-setf-lambda-lists (lambda-list setf-lambda-list)
(do ((ll lambda-list (cdr ll))
(tail lambda-list))
((or (null ll) (member (car ll) '(&optional &rest &key &aux)))
(when (null ll)
(setq tail nil))
(append (ldiff lambda-list tail) setf-lambda-list tail))
(unless (member (car ll) lambda-list-keywords)
(setq tail (cdr ll)))))
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe? We're not going to allow that for
setf of generic functions.
September: This is still hung up on deciding what changes to Common Lisp to
recommend, so as to make setf-functions behave consistently.
2-50 Should we flush multiple-value-prog2, as leading to more discussion than is
warranted by its simplification of the presentation of define-method-combination?
Kempf: Yes.
Moon: Yes.
September: We seem to have forgotten to discuss this.
2-51 It has been suggested that print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
2-54 slot-missing should be documented in chapter 2
Gregor:
slot-missing is a generic function which takes three required
arguments and an optional fourth argument. The three required
arguments are the class of the object, the object and the name of the
slot. The fourth argument is the new value for the slot if
slot-missing is being called by setf of slot-value. This set of
arguments allows people to define methods on the metaclass for
handling slot-missing. For example, a low performance implementation
of dynamic slots could work this way.
(defmethod slot-missing ((class dynamic-class) obj slot
&optional (nv nvp))
(if nvp
(set-dynamic-slot obj slot nv)
(get-dynamic-slot obj slot)))
The default method on slot-missing signals an error of the same name.
September: We changed this slightly. It takes a required fourth argument,
which is a symbol describing the operation being performed on the slot,
one of slot-value, setf, slot-boundp, or slot-makunbound. The optional
new-value argument is now the fifth argument.
Symbol-function (the user callable primitive) needs to be split from the
subprimitive for implementors that gets and sets the "real" function definition
of a symbol. This is so when a symbol's function definition is a generic
function object, the "real" definition can be something that is easier for the
implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
Kempf: I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations.
Moon: Right, the only standardization issue is making sure
SYMBOL-FUNCTION returns the generic function object, not something internal.
Not all of the "corrections and amendments" handed out at the March 1987
X3J13 meeting in Palo Alto have been put into the document yet. The
corrections are in but the amendments and the revised explanation of slot
inheritance are awaiting review by the group. The revised slot inheritance
writeup is later in this file.
==================================================
SMALL ISSUES NEEDING DISCUSSION
1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonable semantics for a GFLET and GFLABELS.
RPG has written a proposal.
September: This proposal was modified and then adopted.
1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens, but in August
Moon said he didn't like it and we should use MEMBER in parameter
specializers instead (there is a proposal for that pending now).
Moon: I favor flushing the QUOTE type specifier.
September: We renamed it from QUOTE to EQL and Gregor will make a
proposal to the cleanup committee.
1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. What operations on that list should be
permitted?
- checking whether it's nil gives the desired feature
- checking its length
- doing something with list elements (presumably method objects)
- modifying the list is clearly out
- does the list have dynamic or indefinite extent?
This may be expensive enough that it can't substitute for
CALL-NEXT-METHOD-OR-NIL.
I think we're awaiting proposals on these two issues, as well as a
concensus on whether we need these features.
September: We adopted a NEXT-METHODS function, scoped the same as
CALL-NEXT-METHOD, and decided that there was no need for a function
such as CALL-NEXT-METHOD-OR-NIL that combines the two.
2-30: Note the third paragraph on p.2-30 of 87-002, speaking of signalling an
error when the arbitrary order of two methods affects the result. I suggest
that this error be mandatory instead of optional.
September: Agreed.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
Gregor: What if by the time you actually run the body of the method, the slot
has an accessor? It all hinges on exactly when macro-expansion time is and
that is not specified.
There are two issues here:
(1) Exactly when is the set of names scoped with with-slots determined?
(2) Exactly when is the presence or absence of an accessor for a name
determined?
We need a proposal.
September: WITH-SLOTS was completely changed; the set of slots is now
listed explicitly, accessors are never called, and both issues go away.
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Gregor: I believe it should signal an error to attempt to put a method on more
than one generic function. My model of this is that if you want to do
something like that, you can take one function, use it as the method function
of multiple methods, each of which would be on a different generic function.
September: Agreed.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor:
This is a generic function like slot-missing. There is a generic
function NO-APPLICABLE-METHOD which is called with the generic function
as the first argument and the arguments to the generic function as
the remaining arguments. This allows people to define a method to
handle the no matching method case either on the class of the generic
function or on the individual generic function. The default method
for no-applicable-method signals an error of the same type.
The error message should give some information about
the classes of the parameters, to help debugging.
CALL-NEXT-METHOD with no more methods should do something similar,
but not identical. Well, we left it simply signalling an error.
September: Agreed.
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
September: deferred.
We need to decide whether class-name of an anonymous class is nil or
signals an error.
The concensus seems to be to return nil.
September: Agreed.
What does type-of return when applied to an instance of an anonymous
class?
September: Agreed that type-of a meta-instance of standard-class returns
(if (eq (symbol-class (class-name (class-of object))) (class-of object))
(class-name (class-of object))
(class-of object))
(This definition might be only approximate when error and timing
considerations are added.)
==================================================
ISSUES WHOSE STATUS IS UNCLEAR, MAYBE TO BE TABLED
2-26 I (Bobrow) believe that short form method combination ought to be a
macro in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
Moon: I oppose this.
September: Dropped.
2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
September: Dropped.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
Gregor: I am pretty sure what we meant was we didn't want to have to worry
about the case where someone returns a closure that includes a call
to call-next-method, and then redefines the class or method structure
so that the closure would have to call different 'next methods'.
Moon: Oh, so this is different from extent, because they could do that
redefinition before the method returns. So either we should say it
captures the set of next methods at a particular instant, or it's
undefined what happens if you redefine.
September: discussion continues in the mail.
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
[no response to this so far, Moon should propose I guess]
September: Postponed.
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
Status depends on whether object-creation proposal includes constructors.
September: Postponed. Moon is to send a proposal for how to add
constructors to the agreed upon object creation protocol, or else
we will flush them.
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
The top level macros and functions should be part of LISP.
The internal functions specified for the sake of metaclass programming
can reside in CLOS.
If CLOS is an optional part of CL, are the symbols in the LISP package
even when the option is not present? Probably.
September: Postponed.
Kempf 29 Jul 87: There was no mention made of compile time optimization,
which I believe I made some initial proposals on in late April or early May.
I've been meaning to revisit them.
September: Postponed.
==================================================
THINGS TO DO ANOTHER DAY
This is a list of issues that were specifically deferred at the September
meeting, and haven't been taken care of yet.
Specify the condition names used by CLOS and their subtype relationships.
Throughout the CLOS spec, specify which condition is signalled where we
now say that an error is signalled.
In general, clean up the terminology, make sure that it is consistent,
and make sure that the document includes a complete and accurate glossary.
Consider renaming "local slot" to "instance slot" and "shared slot" to
"class slot."
Consider defining the term "proper name" to refer to the test involving
class-name and symbol-class that type-of is now defined to do.
Vote on dynamic or indefinite extent of call-next-method, after issues
are explicated in the mail.
Add examples to each operator description in chapter 2.
Reconsider [how?] use of setf and with-added-methods.
Determine inheritance of environments in name-to-object mapping.
Some people want a table in the description of lambda-list congruence.
Some people want a discussion of how to think about the class precedence
list algorithm, showing its effect on some typical class definitions, and
giving some general rules of thumbs that will help people understand the
effect of the CPL algorithm. (This would be things like two trees of
superclasses will remain non-commingled if they are non-intersecting or
intersect only at the top).
Decide about the proposal for a :precedence defclass option.
Look at the amendments distributed in March, determine where new
writing (rather than a simple edit) is required, then determine
who will do the writing.
==================================================
REVISED ``INHERITANCE OF SLOTS AND SLOT OPTIONS'' SECTION:
[For readability all TEX formatting has been temporarily removed]
The set of the names of all slots accessible in an instance of a class,
C, is the union of the sets of names of slots defined by C and its
superclasses. At most one slot of a given name can be accessible in an
instance.
In the simplest case, only one class among C and its superclasses
defines a slot with a given slot name. If the class that defines the
slot is not C, we say that the slot is inherited. The characteristics
of the slot are determined by the slot specifier of the defining class.
If the :allocation slot option is omitted, :instance, or :dynamic, then
it specifies a local slot and each instance of C has its own slot that
stores its own value. If the :allocation slot option is :class, then it
specifies a shared slot, the class that defined the slot stores the
value, and all instances of C access that single slot.
In general, more than one class among C and its superclasses can define
a slot with a given name. In such cases, only one slot with the given
name is accessible in an instance of C, and the characteristics of that
slot are a combination of the several slot specifiers, computed as
follows.
- All the slot specifiers for a given slot name are ordered
from most specific to least specific, according to the order in
the class precedence list of C of the classes that define them.
- The allocation of a slot is controlled by the most specific slot
specifier. If the most specific slot specifier does not contain
an :allocation slot option, :instance is used. Less specific slot
specifiers never affect the allocation.
- The initform of a slot is controlled by the most specific slot
specifier that contains an :initform slot option. If no slot specifier
contains an :initform, the slot has no default initial value form.
- The type of a slot is (and T1 T2 T3...), where T1, T2, T3, and so on
are the :type slot options contained in all of the slot specifiers. If
no slot specifier contains :type, the type is t.
The :reader and :accessor slot options were not mentioned because
they create methods, rather than defining characteristics of a slot.
Reader and accessor methods are inherited in the sense described in the
section ``Inheritance of Methods.''
A consequence of the allocation rule is that shared slots can be
shadowed. If a class C-sub-1 defines a shared slot named S, normally
that single slot is accessible in instances of C-sub-1 and all of its
subclasses. However, if C-sub-2 is a subclass of C-sub-1 and also
defines a slot named S, C-sub-1's slot is not shared by instances of
C-sub-2 and its subclasses. See S2 in the section ``Examples of
Inheritance.''
A consequence of the type rule is that the value of a slot satisfies the
type constraint of each slot specifier that contributes to that slot.
Note that an implementation may or may not choose to check the type of
the new value when initializing or assigning to a slot.
Methods that access slots know only the name of the slot and the type of
the slot's value. Suppose a superclass provides a method that expects
to access a shared slot of a given name and a subclass defines a local
slot with the same name. If the method provided by the superclass is
used on an instance of the subclass, the method accesses the local slot.
==================================================
LAMBDA-LIST CONGRUENCE
Changes to Lambda-list Congruence Rules (p.1-20): Rules 1, 2, and 6 remain the
same, except for wording problems, while rules 3-5 need to be replaced to
implement the new rules for &KEY and to fix the interaction among &KEY, &REST,
and &ALLOW-OTHER-KEYS. The new rules for congruence are the following:
These rules define the congruence of a set of lambda-lists, including the
lambda-list of each method for a given generic function and the lambda-list
specified with DEFGENERIC, if present. For (SETF generic) methods, these
rules apply to the effective lambda-list produced by combining the two
specified lambda-lists according to the rules on page nnn.
1. Each lambda-list must have the same number of required parameters.
2. Each lambda-list must have the same number of optional parameters.
Each method can supply a different default for an optional parameter.
3. If any lambda-list uses &REST or &KEY, each lambda-list must use one or
more of these.
4. If the DEFGENERIC uses &KEY, each method must accept all of the named
arguments mentioned after &KEY in DEFGENERIC, either by accepting them
explicitly, by specifying &ALLOW-OTHER-KEYS, or by specifying &REST but not
&KEY. Each method can accept additional named arguments of its own.
The checking of the validity of named argument names is not done in each
method; instead it is done in the generic function.
5. The use of &ALLOW-OTHER-KEYS need not be consistent across lambda-lists.
If &ALLOW-OTHER-KEYS is used in any lambda-list, then any named arguments
may be used in the call to the generic function.
6. The use of &AUX need not be consistent across methods.
September: Agreed.
==================================================
NAMED ARGUMENTS
Change the meaning of &KEY in the lambda-list of DEFMETHOD and DEFGENERIC:
When a generic function, or its methods, use &KEY in the lambda-list, the
specific set of named arguments accepted by the generic function varies
depending on the applicable methods. The named arguments accepted by the
generic function for a particular call are the union of the named arguments
accepted by any applicable method and the named arguments mentioned after
&KEY in DEFGENERIC, if any. There is no attempt to exclude methods that
are applicable but are not actually called. Note that in standard method
combination, all applicable methods are potentially callable, if
CALL-NEXT-METHOD is used. A method that has &REST, but not &KEY, does not
affect the set of acceptable named arguments. If the lambda-list of any
applicable method or of the DEFGENERIC has &ALLOW-OTHER-KEYS, all named
arguments are accepted by the generic function.
Lambda-list congruence rules require that each method accept all of the named
arguments mentioned after &KEY in DEFGENERIC, either by accepting them
explicitly, by specifying &ALLOW-OTHER-KEYS, or by specifying &REST but not
&KEY. Each method can accept additional named arguments of its own,
in addition to the "standard" named arguments mentioned by DEFGENERIC.
The implementation of &KEY is in three parts:
(1) The function METHOD-NAMED-PARAMETERS retrieves a list of the
named-parameter names (typically, but not necessarily, keyword symbols)
explicitly accepted by a method. If the method's lambda-list contains
&ALLOW-OTHER-KEYS, METHOD-NAMED-PARAMETERS returns that symbol rather than
an infinite list. If the method's lambda-list does not contain &KEY,
METHOD-NAMED-PARAMETERS returns NIL. Note that this means that if the
method's lambda-list contains &REST but not &KEY, it is not considered to
accept any named-arguments explicitly. The implementation of
METHOD-NAMED-PARAMETERS may be in terms of the existing METHOD-LAMBDA-LIST
function.
(2) The macro expansion of DEFMETHOD and related method-defining macros,
when the method uses &KEY, puts &ALLOW-OTHER-KEYS into the lambda-list of
the function. This does not affect the result returned by
METHOD-NAMED-PARAMETERS nor METHOD-LAMBDA-LIST; it simply disables validity
checking of named-argument names when the generic-function-to-method
dispatching mechanism calls the method. Design rationale: it's done with
&ALLOW-OTHER-KEYS, rather than :ALLOW-OTHER-KEYS T, so that methods with
&REST parameters will not see anything extra in their rest parameter.
(3) The generic-function-to-method dispatching mechanism checks the
validity of the argument list when the generic function or any applicable
method uses &KEY and none of them uses &ALLOW-OTHER-KEYS; it cannot rely on
the normal function-call mechanism to check the validity of the argument
list. This is accomplished by collecting the acceptable named-argument
names from the applicable methods and from DEFGENERIC, and checking the
arguments against the union of those lists. If for any applicable method
METHOD-NAMED-PARAMETERS returns &ALLOW-OTHER-KEYS, the whole check is
skipped. CLtL p.62 says named-argument name mismatch "is an error", so the
argument list validity checking in the generic-function-to-method
dispatching mechanism should conform to that and signal an error under
implementation-dependent control.
For example:
(defmethod width ((c character) &key font) ...)
(defmethod width ((p picture) &key pixel-size) ...)
;assume there are no other methods for width and no defgeneric
(width x :font 'foo :pixel-size 10) is an error unless x is
both a character and a picture. The acceptable arguments are
determined by the applicable methods, not all methods.
September: Agreed with changes that have been edited-in above.
==================================================
CLASS REDEFINITION
Clarify redefining classes, find a better name for updating-obsolete-instance.
There was much discussion, which I'm not going to try to summarize here,
and we agreed to adopt a simpler solution than what we had before and to
keep discussing it over the net. Class redefinition, CHANGE-CLASS, and
COERCE will be three independent mechanisms.
∂23-Sep-87 0427 skeene@STONY-BROOK.SCRC.Symbolics.COM draft of built-in method combination types
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Sep 87 04:27:16 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 239385; Wed 23-Sep-87 07:28:16 EDT
Date: Wed, 23 Sep 87 07:27 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: draft of built-in method combination types
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870923072736.4.SKEENE@JUNCO.SCRC.Symbolics.COM>
In September we agreed that CLOS should provide some built-in method
combination types. Yesterday Dave and I chose the most generally
useful ones that Flavors offers. The following text is a draft of a
new section to be added to Chapter 1, after "Declarative Method
Combination". UPPERCASE means bold, and <this> means italic.
Comments are welcomed.
-------------------------------------------------------------------
Built-in Method Combination Types
CLOS provides a set of built-in method combination types. To specify
that a generic function should use one of these method combination
types, give the name of the method combination as the argument to
the :METHOD-COMBINATION option to DEFGENERIC or GENERIC-FUNCTION.
These method combination types act as though they were defined by the
short form of DEFINE-METHOD-COMBINATION. They recognize two roles for
methods.
An :AROUND method has the keyword symbol :AROUND as its sole
qualifier. :AROUND methods work just as they do in standard method
combination. CALL-NEXT-METHOD is supported in :AROUND methods only.
A primary method has the name of the method combination type as its
sole qualifier. For example, the method combination type AND
recognizes methods whose sole qualifier is AND; these are primary
methods.
Each of these method combination types is named after a Lisp operator,
which can be a function, special form, or macro. The effective method
combines all of the applicable primary methods in a call to the Lisp
operator with the same name as the method combination type. That is,
the method combination type produces a Lisp form (<operator> <method-call>
<method-call> ...).
Names of built-in
method combination types
+
AND
APPEND
LIST
MAX
MIN
NCONC
OR
PROGN
The semantics of these types of method combination are:
If there are any :AROUND methods, the most specific :AROUND method is
called. It supplies the value or values of the generic function.
Inside the body of an :AROUND method, CALL-NEXT-METHOD can be used to
immediately call the next method. When the next method returns, the
:AROUND method can execute more code, perhaps based on the returned
value or values. By convention, :AROUND methods almost always use
CALL-NEXT-METHOD.
If an :AROUND method invokes CALL-NEXT-METHOD, the next most specific
:AROUND method is called, if one is applicable. If there are no :AROUND
methods or if CALL-NEXT-METHOD is called by the least specific :AROUND
method, the Lisp operator corresponding to the method combination type
is called. The arguments to that operator include the value or values
returned by each of the applicable primary methods. By default the
order of the primary methods is :MOST-SPECIFIC-FIRST. However, the
order can be reversed by supplying :MOST-SPECIFIC-LAST as the second
argument to the :METHOD-COMBINATION option.
An error is signaled if CALL-NEXT-METHOD is used in a primary method.
An error is signaled if there are no applicable primary methods.
These types of method combination require exactly one qualifier per
method. An error is signalled if there are applicable methods with no
qualifiers, or with qualifiers that are not supported by the method
combination type.
[Note: also need to add the preceding paragraph to page 2-27, in the
discussion of short form of DEFINE-METHOD-COMBINATION.]
∂23-Sep-87 0851 Bobrow.pa@Xerox.COM Terminology: Shared versus class; local versus instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 87 08:51:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 SEP 87 08:51:47 PDT
Date: 23 Sep 87 08:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Terminology: Shared versus class; local versus instance
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870923-085147-13566@Xerox>
The following came up for me in the description of object creation but
is not specific to it
In the current version of the specification there are two sets of terms
used to describe the allocation of slots. These are the key words that
specify the allocation, :class and :instance, and the words "shared" and
"local" respectively. I would like to argue that we consistently use
the key words (or perhaps the word without colons) to distinguish slots
by their allocation. I see the following arguments:
For using local and shared: These words describe the scope of the slots
with respect to an instance -- that is a slot with :allocation :instance
is local to the instance; one with :allocation :class is shared by the
instances.
Against (confusion): Using local and shared in the text will encourage
people to think that the keywords for these allocations are :local and
:shared. Two ways of referring to the same thing is usually a mistake.
Against (extensions): I see several extensions to the :allocation
option that might be usefully experimented with; for example :dynamic,
which is local to the instance, but allocated differently, or :computed
where the procedure used to compute the slot value is shared among
instances, but not the value of the slot.
My proposal is that we always use the keyword itself as the descriptor
for the slots, i.e. :class slots or :instance slots, pronouncing it with
a silent colon.
∂23-Sep-87 0907 Bobrow.pa@Xerox.COM Re: September version of object-creation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 87 09:07:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 SEP 87 09:07:34 PDT
Date: 23 Sep 87 09:06 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: September version of object-creation
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 22 Sep 87 23:04 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870923-090734-13603@Xerox>
A few nits, but otherwise OK with me.
only the form specified by the earliest such class in the CPL
is used.
Replace by "only the form specified by the most specific such class in
the CPL is used.
If two initargs that initialize the same slot, with the same
or different names, are given in the arguments to MAKE-INSTANCE,
the leftmost of these initargs in the initarg list prevails.
The initarg name and the form's value
(from the default-initarg list) are added to the end of
the explicit initarg list.
If there are two different initargs that initialize the
same slot, and one was given explicitly in the arguments to
MAKE-INSTANCE while the other was defaulted via
:DEFAULT-INITARGS, the explicit one prevails.
The first two of these implies the third (correct?).
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
[Should there also be a way to reconstruct the form from
which default-value-function was generated?]
Yes: Perhaps even:
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function init-value-form)...)
since this is probably cached and not hard to compute. It should be
specified that it is undefined as to what happens if you clobber this
list. Similarly for CLASS-DIRECT-SLOT-INITARGS.
∂23-Sep-87 1022 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: September version of object-creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Sep 87 10:22:10 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 239670; Wed 23-Sep-87 13:23:17 EDT
Date: Wed, 23 Sep 87 13:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: September version of object-creation
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870923-090734-13603@Xerox>
Message-ID: <870923132251.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 Sep 87 09:06 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
A few nits, but otherwise OK with me.
Thanks. I updated the file according to your comments, all of which
I agreed with.
∂23-Sep-87 1240 skeene@Riverside.SCRC.Symbolics.COM the new DEFMETHOD syntax
Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 23 Sep 87 12:40:32 PDT
Received: from JUNCO.SCRC.Symbolics.COM by Riverside.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168478; Wed 23-Sep-87 14:35:02 EDT
Date: Wed, 23 Sep 87 14:35 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: the new DEFMETHOD syntax
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870923143539.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
This message reflects the decisions made last week to change DEFMETHOD
syntax to "refer to" each specialized parameter, and to use EQL instead
of QUOTE for individual methods.
The changes to DEFMETHOD syntax require the following changes to the
specification:
p 2-34: add this to Remarks:
The DEFMETHOD macro ``refers to'' each specialized parameter (see the
description of IGNORE in Common Lisp: the Language, page 160). This
includes parameters that specialize on T. This means that a compiler
warning does not occur whether or not the body of the method refers to a
specialized parameter. Note that a parameter that specializes on T is
not synonymous with an unspecialized parameter in this context.
p 2-33, in Syntax: Change (QUOTE <datum>) to (EQL <form>)
p 2-34, second paragraph: Change (QUOTE <object>) to (EQL <form>)
p 1-20, second bullet: Change (QUOTE <object>) to (EQL <form>)
p 1-20, replace first paragraph with this:
A parameter specializer name denotes a parameter specializer as follows:
Let N be a parameter specializer name and P be the corresponding
parameter specializer. If N is a class name, then P is the class with
that name. If N is (EQL <form>), then P is (EQL <object>), where <object>
is the result of evaluating <form>.
p 1-20, fifth paragraph: Change (QUOTE <object>) to (EQL <object>)
p 1-20, seventh paragraph: Change (QUOTE <object>) to (EQL <object>)
p 1-20, seventh paragraph: Replace last two sentences with:
The only parameter specializer that can be a list is (EQL <object>). This
proposal requires that Common Lisp be modified to include (DEFTYPE EQL
(<object>) `(MEMBER ,<object>)).
p 1-21, first paragraph: Remove last sentence, and replace it with a
new paragraph:
For method combination types defined by the short form of
DEFINE-METHOD-COMBINATION and the built-in method combination types, a
primary method has the name of the method combination type as its sole
qualifier. These method combination types also support auxiliary
methods, which have :AROUND as their sole qualifier.
∂23-Sep-87 1330 Bobrow.pa@Xerox.COM Re: the new DEFMETHOD syntax
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Sep 87 13:30:09 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 SEP 87 13:27:21 PDT
Date: 23 Sep 87 13:27 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: the new DEFMETHOD syntax
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 23 Sep 87 14:35 EDT
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870923-132721-14012@Xerox>
Looks good.
danny
∂23-Sep-87 2202 RPG September version of object-creation (More nits)
To: common-lisp-object-system@SAIL.STANFORD.EDU
In 87-002, we have tried to use the term ``parameter'' to refer to the
thing that appears in a lambda-list and ``argument'' to refer to the thing
that gets passed to the lambda-expression. In the writeup of initialization,
we (that is, whoever writes it) ought to be careful to keep this
disctinction in mind. I think it is ok to call the things :initargs and
the like if we are careful.
-rpg-
∂23-Sep-87 2218 RPG Returning From a Generic Function
To: common-lisp-object-system@SAIL.STANFORD.EDU
It appears there is approximate consensus on there being an
implicit block in a DEFMETHOD as there is in DEFUN. Upon some
reflection, I agree there is no need to provide a way to return
from a generic function, because anyone who wants to do such a thing
in the presence of method combination should be hairy enough to
know how to use an :around method to do it.
-rpg-
∂24-Sep-87 0856 Bobrow.pa@Xerox.COM no-applicable-method
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 08:55:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 08:55:16 PDT
Date: 24 Sep 87 08:55 PDT
From: Bobrow.pa@Xerox.COM
Subject: no-applicable-method
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-085516-15017@Xerox>
( no-applicable-method generic-function first-argument &rest
all-arguments)
If a generic function is invoked and no method of the generic function
is applicable, the generic function no-applicable-method is called.
The generic-function argument to no-applicable-method is the
generic-function object from which no-applicable-method was called. The
&rest argument, all-arguments, is a list of all arguments to the
original generic function. The parameter first-argument is bound to the
value of the first argument in the orginal call to the generic function.
The first argument has been pulled out to make it easier to specialize
no-applicable-method in ways that has been found useful in classical
object-oriented programming systems (see below for an example). In the
case where the generic function has no arguments, the value of
first-argument is nil; in this case, of course, the value of
all-arguments is ().
The generic function no-applicable-method is not intended to be called
by programmers. Programmers are expected to write methods for it.
The function no-applicable-method is called only by the discriminator
code in the generic function. The default method on
standard-generic-function signals an error.
Example: By supporting easy specialization on the first argument to the
generic function, we make it possible to build message forwarders using
no-applicable-method. In classical object oriented programming, a
forwarder is an object that packages up any message that it receives,
and forwards it on to one or more other objects. This can be used to
build a distributed object system that runs on several machines. If an
object, O1, resides on machine A, on machine B it is represented by a
forwarder, OF-1. This forwarder, OF1, packages up messages sent to
OF-1, and transmits them to the O1 on machine A.
To use no-applicable-method to build forwarders, we need a class that
is not a subclass of any class except T; hence no methods specialized
on this argument will be applicable to instances of this class. Hence
all calls using an instance of this class as first argument will cause a
trap to no-applicable-method. We write:
(defmethod no-applicable-method (g-f (first forwarder) &rest args)
(send-elsewhere *place* gf first args)))
In addition to this use for distibuted system implementation (see
distributed Smalltalk paper), a similar use of no-applicable-method will
allow exploration of techniques of delegation promoted by Lieberman; he
claims that delegation is a good alternative to inheritance to allow
objects to share code.
∂24-Sep-87 0907 Bobrow.pa@Xerox.COM next-methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:07:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:03:58 PDT
Date: 24 Sep 87 09:03 PDT
From: Bobrow.pa@Xerox.COM
Subject: next-methods
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-090358-15034@Xerox>
next-methods
In a method, one can use the locally defined function next-methods to
obtain a list of the method objects. The first of these is the method
that would be invoked by call-next-method. It is undefined what happens
if the user modifies this list. An obvious use of the returned list is
to test the length of the list; if zero, then an invocation of
call-next-method would fail.
The function next-methods is local, and takes no arguments.
next-methods has the same scope and extent as call-next-method.
∂24-Sep-87 0915 Bobrow.pa@Xerox.COM Redefining Classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:15:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:12:59 PDT
Date: 24 Sep 87 09:12 PDT
From: Bobrow.pa@Xerox.COM
Subject: Redefining Classes
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-091259-15052@Xerox>
Redefining Classes
When a defclass form is evaluated and a class with the given name
already exists, the existing class is redefined. This may also cause
some of the subclasses of the redefined class to also be redefined.
Classes my also be redefined using the metaobject protocol -- see the
functions add-named-class and update-class.
For instances of standard-class, redefining a class modifies the
existing class object to reflect the new class definition; it does not
create a new class object for the class. Any method created by an
:accessor, :reader, specified by the old defclass form is removed from
the corresponding generic function unless that same method is specified
by the new defclass form.
If the redefinition of a class causes the structure of its instances to
be different, and the class has instances, then the generic function
make-instances-obsolete is called. The function make-instances-obsolete
takes as its one argument the class to be redefined. This invocation
captures the state of the class before redefinition, and marks all
existing instances of the class as obsolete. Such instances will be
updated to the new structure determined by the class redefinition. This
updating will be done in such a way that users will never see an
instance with the obsolete structure. THIS IS ONLY GUARANTEED TO BE
SUPPORTED FOR CLASSES THAT ARE INSTANCES OF STANDARD CLASS.
make-instances-obsolete class (generic-function)
Obsolete instance updating is done in two stages:
1) The system creates a property list that captures the slot names and
values of all the slots of the obsolete instance. It then transforms
the structure of the instance, so that it conforms to the current class
definition. All the slots of this transformed instance are
uninitialized. This first stage cannot be seen by user programs.
2) The generic function update-obsolete-instance is called. Its
arguments are the transformed instance, and the property list of
slot-names and values corresponding to the state of the obsolete
instance. Its contract is to do appropriate updating of the instance,
using the values from the obsolete slots.
Because update-obsolete-instance is user code, its operation can be seen
by the user; but the model that CLOS supports is that as far as the user
can tell, all the existing instances of a class are updated as soon as
the class redefinition happens. This implies that the user must define
a method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing instances
(for example, to method call or slot access time), but users should
never be able to see the untransformed instance.
update-obsolete-instance instance property-list (generic-function)
The method on update-obsolete-instance defined on the class Object does
the following:
1) for each instance slot in current definition of class, if its
slot-name appears in the property list, the value corresponding to the
slot-name in the property-list is installed in the instance slot. Class
slots in the current definition of class are assumed to have their
correct value, and are not changed.
2) For any slot in the instance which is still unbound, and for which
there is an :initform expression in the current class definition, the
initform is evaluated and the value installed in that slot.
The generic function update-obsolete-instance is not intended to be
called by programmers. Programmers are expected to write methods for
it. The function update-obsolete-instance is called by the system to
update an obsolete instance.
∂24-Sep-87 0919 Bobrow.pa@Xerox.COM DRAFT: Changing Names of Built-in classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:18:54 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:19:27 PDT
Date: 24 Sep 87 09:19 PDT
From: Bobrow.pa@Xerox.COM
Subject: DRAFT: Changing Names of Built-in classes
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-091927-15071@Xerox>
The class associated with a particular symbol can be changed by using
setf with the accessor symbol-class. It is undefined what happens if
the user attempts to change the class associated with a symbol that is
defined as a type specifier in CLtL.
e.g. (SETF (SYMBOL-CLASS 'CONS) ...)
∂24-Sep-87 0919 Bobrow.pa@Xerox.COM Unbound Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:17:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:18:08 PDT
Date: 24 Sep 87 09:17 PDT
From: Bobrow.pa@Xerox.COM
Subject: Unbound Slots
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-091808-15069@Xerox>
NOTE: The name
slot-uninitialized
has been changed to
slot-unbound
Not all slots in an instance need to be bound. This can happen if a
slot has no :initform, an has not been set, or if the user has called
slot-makunbound. Referencing an unbound slot of an instance of a
standard class causes the generic-function slot-unbound to be invoked.
The arguments to slot-unbound are the same as the arguments to
slot-value-using-class, that is, the class of the instance whose slot
was accessed, that instance, and the name of the slot.
The generic function slot-unbound is not intended to be called
by programmers. Programmers are expected to write methods for it.
The function slot-unbound is called only by the function
slot-value-using-class.
slot-unbound class instance slot-name (generic function)
The slot-unbound method on standard-class signals an error.
∂24-Sep-87 0927 Bobrow.pa@Xerox.COM slot-missing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:27:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:27:49 PDT
Date: 24 Sep 87 09:27 PDT
From: Bobrow.pa@Xerox.COM
Subject: slot-missing
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-092749-15093@Xerox>
slot-missing
If an attempt is made to access a slot in an instance of a standard
class, and the name of the slot provided is not a name of a slot in that
class, then the generic function slot-missing is invoked.
slot-missing class instance slot-name operation
&optional new-value
The required arguments to slot-missing are the class of the instance
being accessed, the instance, the slot-name, a symbol that indicates the
operation which caused the trap to slot-missing. The optional argument
to slot-missing is used when the operation is attempting to set the
value of the slot.
The generic function slot-missing is not intended to be called by
programmers. Programmers are expected to write methods for it.
The generic function slot-missing is called by
slot-value-using-class
(setf slot-value-using-class)
slot-bound-p
For each of these operations the corresponding symbol for the operation
argument is
slot-value
setf
slot-boundp
The default method on slot-missing signals an error.
This set of arguments (including the class of the instance) facilitates
defining methods on the metaclass for handling slot-missing. For
example, this enables an easy implementation of dynamic slots; that is:
(defmethod slot-missing ((class dynamic-class) obj slot operation
&optional nv)
(ecase operation
(slot-value (get-dynamic-slot obj slot))
(setf (set-dynamic-slot obj slot nv)
(slot-boundp (exists-dynamic-slot-p obj slot))))
∂24-Sep-87 0937 Moon@STONY-BROOK.SCRC.Symbolics.COM September version of object-creation (More nits)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:37:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240528; Thu 24-Sep-87 12:38:48 EDT
Date: Thu, 24 Sep 87 12:38 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: September version of object-creation (More nits)
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Sep 87 01:02 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870924123827.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 23 Sep 87 2202 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
In 87-002, we have tried to use the term ``parameter'' to refer to the
thing that appears in a lambda-list and ``argument'' to refer to the thing
that gets passed to the lambda-expression. In the writeup of initialization,
we (that is, whoever writes it) ought to be careful to keep this
disctinction in mind. I think it is ok to call the things :initargs and
the like if we are careful.
Agreed completely. In the latest version I mailed out, I made some
effort to straighten this out, however I think additional effort is
likely to be needed.
I just re-read CLtL pp.61-3. The stickiest terminological problems in
my writeup have to do with finding replacements for CLtL's terms "keyword
parameter" and "keyword name" that don't contain the word "keyword". CLtL
uses "keyword name" in connection with both arguments and parameters, so
you can see where my attempt to substitute "named-argument name" runs into
trouble.
Do you think it would be worth trying a version of the writeup that uses
CLtL's terminology, with a simple admonition that a "keyword name" is not
necessarily a keyword symbol? After all, CLtL also has "lambda list keywords",
so maybe "keyword" in Common Lisp means "any symbol that identifies a syntactic
position" rather than "(eq (symbol-package symbol) (find-package 'keyword))".
I surveyed the writeup and it looks like the changes would be these:
named argument -> keyword argument
named argument name -> keyword name
"initarg name" remains unchanged
named-parameter name -> keyword parameter specifier's keyword name
(wordy, but CLtL doesn't seem to use a shorter term for this)
METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS
(returns a list of keyword names, not parameter specifiers)
Opinions?
∂24-Sep-87 0942 Moon@MEAD.SCRC.Symbolics.COM Terminology: Shared versus class; local versus instance
Received: from [128.81.41.234] by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:42:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by MEAD.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 95280; Thu 24-Sep-87 12:43:30 EDT
Date: Thu, 24 Sep 87 12:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Terminology: Shared versus class; local versus instance
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870923-085147-13566@Xerox>
Message-ID: <870924124333.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Either terminology would be okay with me, as long as they are used
consistently.
Note that by recourse to old documents you can discover that the
term "local slot" was introduced to cover both ":allocation :instance"
and ":allocation :dynamic" slots. No doubt the existence of :dynamic
meant that it would have been confusing to call these "instance slots".
Now that :dynamic is gone, it would be okay with me to simplify things
by calling the two kinds of slots "instance" and "class". Do you think
that this terminological change might cause trouble for implementations
that experiment with extensions, such as dynamic slots? (Of course
one might wonder in this connection why no one ever proposed dynamic
class slots, in other words, why the static/dynamic distinction was
thought to be on the same axis as the local/shared distinction.)
∂24-Sep-87 0951 Bobrow.pa@Xerox.COM Re: September version of object-creation (More nits)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:51:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:45:03 PDT
Date: 24 Sep 87 09:44 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: September version of object-creation (More nits)
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 24 Sep 87 12:38 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870924-094503-15151@Xerox>
METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS
(returns a list of keyword names, not parameter specifiers)
Then this should be called METHOD-KEYWORD-NAMES, n'est pas?
danny
∂24-Sep-87 0957 Moon@STONY-BROOK.SCRC.Symbolics.COM slot-missing
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:56:34 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240552; Thu 24-Sep-87 12:57:44 EDT
Date: Thu, 24 Sep 87 12:57 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: slot-missing
To: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <870924-092749-15093@Xerox>
Message-ID: <870924125723.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Sep 87 09:27 PDT
From: Bobrow.pa@Xerox.COM
The generic function slot-missing is called by
slot-value-using-class
(setf slot-value-using-class)
slot-bound-p
For each of these operations the corresponding symbol for the operation
argument is
slot-value
setf
slot-boundp
That should be
The generic function slot-missing is called by
slot-value-using-class
(setf slot-value-using-class)
slot-boundp-using-class
slot-makunbound-using-class
For each of these operations the corresponding symbol for the operation
argument is
slot-value
setf
slot-boundp
slot-makunbound
Otherwise it's fine.
∂24-Sep-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: September version of object-creation (More nits)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:01:29 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240560; Thu 24-Sep-87 13:02:43 EDT
Date: Thu, 24 Sep 87 13:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: September version of object-creation (More nits)
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870924-094503-15151@Xerox>
Message-ID: <870924130228.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 24 Sep 87 09:44 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS
(returns a list of keyword names, not parameter specifiers)
Then this should be called METHOD-KEYWORD-NAMES, n'est pas?
Mais oui.
∂24-Sep-87 1021 Bobrow.pa@Xerox.COM Re: Terminology: Shared versus class; local versus instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:21:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 10:20:09 PDT
Date: 24 Sep 87 10:19 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Terminology: Shared versus class; local versus instance
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 24 Sep 87 12:43 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870924-102009-15244@Xerox>
Note that by recourse to old documents you can discover that
the term "local slot" was introduced to cover both ":allocation
:instance" and ":allocation :dynamic" slots. No doubt the
existence of :dynamic meant that it would have been confusing to
call these "instance slots". Now that :dynamic is gone, it would be
okay with me to simplify things by calling the two kinds of slots
"instance" and "class". Do you think that this terminological
change might cause trouble for implementations that experiment with
extensions, such as dynamic slots?
No, because one could use "instance or dynamic" to cover the union. The
name now is specific to the specified allocation rather than to a
property of that allocation.
(Of course one might wonder in this connection why no one ever
proposed dynamic class slots, in other words, why the
static/dynamic distinction was thought to be on the same axis as
the local/shared distinction.)
Dynamic slots were proposed as an efficiency measure for slots that were
seldom used, the argument was that it was better not to allocate space
in each instance. For class slots, allocation is only once per class.
danny
∂24-Sep-87 1051 Masinter.pa@Xerox.COM Re: next-methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:51:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 10:52:19 PDT
Date: 24 Sep 87 10:52 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: next-methods
In-reply-to: Bobrow.pa's message of 24 Sep 87 09:03 PDT
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-105219-15293@Xerox>
What's next-methods for? I'm having trouble imagining a use, and no
trouble imagining difficulties implementing it. In particular, it means
that you need to provide access to the entire list of subsequent methods
rather than just the next one.
∂24-Sep-87 1124 RPG NEXT-METHODS
To: common-lisp-object-system@SAIL.STANFORD.EDU
Larry writes:
``What's next-methods for?''
Among other things, it's so that a program can know whether
call-next-method will signal an error the next time around.
I think there is a second reason for it, which is to provide
some window onto the hidden state within a generic function.
-rpg-
∂24-Sep-87 1142 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: next-methods
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 11:41:52 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240696; Thu 24-Sep-87 14:42:04 EDT
Date: Thu, 24 Sep 87 14:41 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: next-methods
To: Masinter.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <870924-105219-15293@Xerox>
Message-ID: <870924144150.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 24 Sep 87 10:52 PDT
From: Masinter.pa@Xerox.COM
What's next-methods for? I'm having trouble imagining a use, and no
trouble imagining difficulties implementing it. In particular, it means
that you need to provide access to the entire list of subsequent methods
rather than just the next one.
In my envisioned implementation the list would not be materialized unless
someone actually called next-methods, and I think none of the mechanism
would be present unless there was actually a lexical reference to next-methods.
That is, the generic function works slightly differently if somewhere in
the effective method, next-methods is used. Much the same thing will be
done for call-next-method.
If I hadn't been thinking along those lines, I might have made the same
objection you raised.
∂24-Sep-87 1458 Gregor.pa@Xerox.COM Re: next-methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 14:58:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 14:56:32 PDT
Date: 24 Sep 87 14:56 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: next-methods
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 24 Sep 87 14:41 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Masinter.pa@Xerox.COM, Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-145632-15708@Xerox>
I suspect that the implementation I envision is a lot like the one Moon
does.
I can't see any reason why implementing next-methods would be harder
than call-next-methods.
∂24-Sep-87 1549 Masinter.pa@Xerox.COM Re: next-methods
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 15:49:07 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 15:49:38 PDT
Date: 24 Sep 87 15:49 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: next-methods
In-reply-to: Gregor.pa's message of 24 Sep 87 14:56 PDT
To: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870924-154938-15779@Xerox>
Even if there are implementations in which it is easy, my original
question stands: when would you use such a thing? Its just not in the
list of 20 obvious things that I can imagine wanting to get hold of.
∂24-Sep-87 2035 Moon@STONY-BROOK.SCRC.Symbolics.COM Redefining Classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 20:34:44 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 241155; Thu 24-Sep-87 23:35:55 EDT
Date: Thu, 24 Sep 87 23:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Redefining Classes
To: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <870924-091259-15052@Xerox>
Message-ID: <870924233529.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Sep 87 09:12 PDT
From: Bobrow.pa@Xerox.COM
Redefining Classes
This is okay for the most part, but I have a few comments to offer
on excerpts from your proposal. There are a few areas that need to
be tightened up, plus one major defect. I'll conclude with a somewhat
random comment about multiprocess systems.
If the redefinition of a class causes the structure of its instances to
be different...
I think we're going to have to define this more precisely. I see two
options:
(1) Adding or removing an instance slot definitely changes the structure,
and some other operations may also change the structure, depending on the
implementation.
(2) The structure changes if and only if the value of
(class-all-instance-slot-names class) is not EQUAL to its previous value.
I made up the function name class-all-instance-slot-names, but you get
the idea. Note how class-all-slot-names won't work.
The big difference between option 1 and option 2 is that with option 2,
a given sequence of defclass forms will produce exactly the same
sequence of calls to make-instances-obsolete in all implementations.
I'm inclined to option 2, because it is more precise, but I'm worried
that this might rule out some implementation possibility. Also, for
this to be meaningful and portable, we have to define the exact order of
slots produced by slot inheritance, which is not something we've had to
specify before now.
Obsolete instance updating is done in two stages:
1) The system creates a property list that captures the slot names and
values of all the slots of the obsolete instance. It then transforms
the structure of the instance, so that it conforms to the current class
definition. All the slots of this transformed instance are
uninitialized. This first stage cannot be seen by user programs.
2) The generic function update-obsolete-instance is called. Its
arguments are the transformed instance, and the property list of
slot-names and values corresponding to the state of the obsolete
instance. Its contract is to do appropriate updating of the instance,
using the values from the obsolete slots.
I have two problems with this. The easy problem is that I don't like
the name update-obsolete-instance, because the instance doesn't really
seem obsolete to me. One idea is to take an analogy to class-changed
and call it class-redefined. In Flavors we call it transform-instance,
but it doesn't have quite the same semantics. It's likely that someone
can think of a better name than any of these.
Much more important, I can't implement the specification that the slots
are initially uninitialized and then they are filled in from values
saved in a property list. There are two problems, one obvious and one
subtle. The obvious problem involves slots that were unbound originally;
since there is no Lisp value that means "unbound", there is nothing that
can be put into the property list for these slots. But if we don't put
any entry in the property list, then the desired feature that the method
can tell which slots were added or removed is lost; these slots look like
they were added, even though they weren't. Also, the default method you
mention below will put the :initform value into these previously unbound
slots, which seems wrong. "Unbound" should not be confounded with
"nonexistent."
The subtle problem involves some language extensions that we have,
allowing slots to have contents that cannot be expressed as Lisp values
in a property list. For instance, there is a mechanism similar to
Prolog logic-variables which allows two slots to be linked together.
This linkage has to be preserved in the face of class redefinition.
For these reasons, I believe it is better to specify that the slot
values are conveyed from the old structure of the instance to the new
structure by the low-level implementation, not by a user-replaceable
method. Thus when the generic function update-obsolete-instance is
called, all slots that existed in the old class definition, and
existed as instance slots in the new class definition, already have
their values, as the same low-level bits. I can't see any need for
even a meta-user to replace this with something else.
Now we have to ask what information the update-obsolete-instance method
needs. If I remember last week's discussion, the idea of passing in a
property list was that it contained the set of old slots, and by querying
the class one could get the set of new slots, and thus the added and
deleted slots could be determined. Unfortunately unbound slots break this,
since either they can't have property list entries or the property list
entry has to contain a made-up value. I suggest conveying the desired
information directly, rather than trying to be clever: Give
update-obsolete-instance four arguments:
the instance
a list of the names of all added slots
a list of the names of all deleted slots
a property list giving the values of all deleted, bound slots
I think this conveys all relevant information directly, and it's
probably less consing than the full property list.
Because update-obsolete-instance is user code, its operation can be seen
by the user; but the model that CLOS supports is that as far as the user
can tell, all the existing instances of a class are updated as soon as
the class redefinition happens. This implies that the user must define
a method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing instances
(for example, to method call or slot access time), but users should
never be able to see the untransformed instance.
We're going to have to specify this a little more precisely, I suspect.
We should specify when is the latest time that an implementation can call
update-obsolete-instance, and then say that it is permitted to call it
any time earlier (after the class has been redefined). I now believe
that the latest time can simply be the time any of the four slot access
and modification functions (or internal equivalent) is called, in spite
of all the flaming against this we engaged in while discussing Danny's
proposal at the meeting last week.
The method on update-obsolete-instance defined on the class Object does
the following...
Instead, I would say the default method initializes only the newly added
slots.
Multiprocess systems are going to have to be careful about what happens
if other processes access the object before update-obsolete-instance
returns. I don't like the way Flavors does this now, which is: allocate
any new storage and evaluate any necessary initforms; with other
processes locked out, check again that the instance is still obsolete,
then convey the slots to the new storage and link things up, now with
processes running freely again, call the user's methods. Maybe the
user's methods should run with other processes locked out, especially if
newly added slots are only initialized by these methods. Of course CLOS
doesn't have to say anything about the extension to multiple processes.
∂25-Sep-87 1208 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Exact type
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Sep 87 12:08:26 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab14626; 25 Sep 87 14:34 EDT
Received: from ti-csl by RELAY.CS.NET id ap18322; 25 Sep 87 14:17 EDT
Received: from Jenner by tilde id AA16860; Tue, 22 Sep 87 11:22:12 CDT
Message-Id: <2768315111-8803361@Jenner>
Date: Tue, 22 Sep 87 11:25:11 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Exact type
I have second thoughts about allowing any common lisp type
in (declare (exact-type ...))
- First, what does exact-type means?
Since type-of cannot be trusted to return the most specific type an
object is of, we have to base our definition on TYPEP.
I propose this one:
x is of exact-type X if it verifies:
Let Y be a type such as (SUBTYPEP X Y) is true,
then (TYPEP x Y ) is false.
I think it does what JAK meant.
- Assuming that my definition is correct, for which type does it make
sense?
It makes sense for our classes since all the subclasses can be known,
they are user classes.
By the same token, it makes sense for defstruct types.
But allowing the other COMMON subtypes would makes programs non portable:
The list of subtypes of a type is implementation dependent. We say (page
1-14) that individual implementation can add additional subclass
relationships as long as they don't violate CLtL.
I propose that we restrict the types acceptable to (declare (exact-type
...)) to CLOS classes and structure types.
Patrick.
∂25-Sep-87 1258 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: fixing our problems with setf
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Sep 87 12:58:09 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad14604; 25 Sep 87 14:32 EDT
Received: from ti-csl by RELAY.CS.NET id af18322; 25 Sep 87 14:14 EDT
Received: from Jenner by tilde id AA14104; Tue, 22 Sep 87 09:33:34 CDT
Message-Id: <2768308570-8410382@Jenner>
Date: Tue, 22 Sep 87 09:36:10 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Gregor.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: fixing our problems with setf
In-Reply-To: Msg of 20 Sep 87 19:03 PDT from Gregor.pa@xerox.com
Date: 20 Sep 87 19:03 PDT
From: Gregor.pa@xerox.com
Subject: fixing our problems with setf
Unless we can get setf 'fixed' in the entire language, I propose that we
solve our problems with setf by eliminating all the setf features from
CLOS (except automatically generated writer methods). That means get
rid of the ability to say (setf <foo>) to defmethod, symbol-function,
generic-function-labels, generic-flet and the others.
My belief is that we are geting into trouble because we are confusing
(generic) function naming with defining setf macros. This gets us
screwed because setf is a macro in yet another namespace and doesn't
interact real well with our stuff.
Put another way, there isn't (right now) anything called defun-setf. If
you want to do that you have to do (something like):
(defsetf foo |setf FOO|)
(defun |setf FOO| (x new-value) ...)
Given that, I don't see whats so wrong with having to do:
(defsetf bar |setf BAR|)
(defmethod |setf BAR| ((x boat) new-value) ..)
The problem is that we can't always specialize on the new-value argument
using the short defsetf form. The programmer will have to write a hocky
defsetf form to get around the problem of having optional arguments
(e.g. implementing the setf form of SUBSEQ as a generic function). We
lose the COMBINE-LAMBDA-LISTS abstraction.
I agree with Masinter, if we don't propose a fix, nobody will fix it.
Our haste of finishing the specs shouldn't make us adopt a short term
view when we know what the long term solution should be.
Patrick.
∂25-Sep-87 1841 Moon@STONY-BROOK.SCRC.Symbolics.COM Amendments requiring additional writing
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Sep 87 18:40:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242001; Fri 25-Sep-87 21:41:23 EDT
Date: Fri, 25 Sep 87 21:41 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Amendments requiring additional writing
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870925214129.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
I looked through the Amendments handed out at the March X3J13 meeting,
with an eye to Dick's comments that some of them couldn't just be edited
into the document, but required significant additional writing. Here is
suggested writing for the ones that don't already have suggested writing.
There might also be a problem of the suggested writings being hard to
understand, inappropriate, or incorrect; if so, we should discuss those
over the mail.
1-11: Replace the last paragraph with the following two paragraphs:
If in the new version of the class there is a local slot of the same
name as any slot in the old version of the class, the value of that slot
will be the same in both instances. This means that if the slot has a
value, the value returned by {\bf slot-value} after {\bf change-class}
is invoked is {\bf eql} to the value returned by {\bf slot-value} before
{\bf change-class} is invoked. Similarly, if the slot was
uninitialized, it remains uninitialized.
At the moment a class is redefined, if the new version of the class
contains a shared slot of the same name as any shared slot in the
old version of the class, the value of that slot will be the same
in both. If in the new version of the class there is
a shared slot of the same name as any local slot in the old version of
the class, that shared slot is initialized to the value of the
corresponding {\bf :initform} option of the new class, or remains
uninitialized if the new version of the class does not specify or
inherit the {\bf :initform} option for that slot. Shared slots
are not affected by the updating of an instance.
[1-11 will also get some changes to reflect the new scheme for
redefining classes, which does not use change-class, and some of the
existing text will be recycled as a description of change-class, however
I'm not trying to address those here.]
2-54:
subtypep Function
Purpose:
The Common Lisp function {\bf subtypep} is extended to accept
class objects as type-specifiers.
Syntax:
{\bf subtypep} {\it type1} {\it type2}
Arguments:
{\it type1} and {\it type2} are type specifiers of any kind, including
class objects.
Values:
The first value is {\it true} if {\it type1} is definitely a
(not necessarily proper) subtype of {\it type2}. The second value
indicates the certainty of the result.
type-of Function
Purpose:
The Common Lisp function {\bf type-of} is extended to accept an instance
of any class as its argument. For instances of standard classes,
{\bf type-of} returns the class name when one exists, otherwise the
class object.
Syntax:
{\bf type-of} {\it object}
Arguments:
{\it object} is any object.
Values:
The result is a type-specifier such that
{\bf (typep {\it object} '{\it result})} is true.
If {\bf (class-of {\it object})} is an instance of {\bf standard-class},
{\bf type-of} behaves as if it was defined by
\screen!
(defun type-of (object)
(let* ((class (class-of object))
(class-name (class-name class)))
(if (and class-name
(cboundp class-name)
(eq (symbol-class class-name) class))
class-name
class)))
\endscreen!
typep Function
Purpose:
The Common Lisp function {\bf typep} is extended to accept
class objects as type-specifiers.
Syntax:
{\bf typep} {\it object} {\it type}
Arguments:
{\it object} is any object.
{\it type} is a type specifier of any kind, including a
class object.
Values:
The value is {\it true} if {\it object} is of type {\it type}.
∂26-Sep-87 1639 Masinter.pa@Xerox.COM Re: Amendments requiring additional writing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Sep 87 16:39:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 26 SEP 87 16:40:22 PDT
Date: 26 Sep 87 16:40 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Amendments requiring additional writing
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 25 Sep 87 21:41 EDT
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870926-164022-17885@Xerox>
While fixing typep and subtypep to deal with classes seems likely to
preferable to adding instancep and subclassp, attempting to fix type-of
so that it sometimes returns a class and sometimes returns a symbol
seems hopeless, and bad design. type-of is so underconstrained in any
case to be worthless. I think you're better off abandoning it -- e.g.,
implementations can return T if on instances of classes if they need to.
The proponents for disallowing careless name->value mappings will likely
be unhappy with the polymorphic typep and subtypep; it might be useful
to be able to lexically determine whether they might be used in a given
program.
Does anyone else see a linkage between the function-type proposal and
the form for typep/instancep subtypep/subclassp type-of/class-of?
∂28-Sep-87 0623 muehle%orion@cs.utah.edu remove me from the list
Received: from CS.UTAH.EDU by SAIL.STANFORD.EDU with TCP; 28 Sep 87 06:23:42 PDT
Received: by cs.utah.edu (5.54/utah-1.0)
id AA12716; Mon, 28 Sep 87 07:23:27 MDT
Received: by orion.utah.edu (5.54/utah-1.0-slave)
id AA05499; Mon, 28 Sep 87 07:23:17 MDT
Date: Mon, 28 Sep 87 07:23:17 MDT
From: muehle%orion@cs.utah.edu (Eric Muehle)
Message-Id: <8709281323.AA05499@orion.utah.edu>
To: common-lisp-object-system@sail.stanford.edu
Subject: remove me from the list
muehle@orion.utah.edu
ERIC
∂28-Sep-87 0842 kempf%hplabsz@hplabs.HP.COM Various Topics Discussed Last Week
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 08:42:03 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 08:41:46 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 28 Sep 87 09:42:32 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Various Topics Discussed Last Week
X-Mailer: mh6.5
Date: Mon, 28 Sep 87 09:42:29 MST
Message-Id: <16906.559842149@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
After an unsuccessful search for desert bighorn sheep at 9,000 feet in
the eastern Nevada mountains, here are some comments on the week's mail:
1) On SETF:
I agree with Gregor that we should drop SETF methods from the language
for now. I don't think requiring the user to write a DEFSETF is excessive,
since SETF is currently just syntatic sugar anyway. I think I understand
Patrick's concerns about not being able to use the short form, but am
concerned that, if we don't drop DEFMETHOD-SETF and kin we may be wiring
short term solutions into the spec which would preclude making an underlying
fix, as Masinter and Gregor have suggested. I agree that we should
propose a fix. I like Moon's way of defining a SETF function, and the
idea of function specs in general. We seem to be continually stumbling
on where they can be useful (DOCUMENTATION, TRACE, SETF functions, etc.).
I think the addition of methods and generic functions to Common Lisp
has magnified this lack in the underlying language.
For purposes of finalizing the spec for the November meeting, I think we
should drop reference to SETF methods. I'd like to co-ordinate the TRACE
proposal to the cleanup committee along with anything Gregor might
propose involving function specs.
2) On blocks in methods:
I agree that Alternative 1 would be best. Users who want something
different can either use a :AROUND method, as Moon suggested, or
program their own generic function dispatching function, using
the metaobject protocol.
2) On dynamic v.s. indefinite extent for CALL-NEXT-METHOD:
Dynamic it is.
3) On the object creation proposal:
Here are some specific comments on Moon's basenote:
> The form
>is evaluated in the lexical environment in which the DEFCLASS form was
>evaluated.
When reading this, it sounded like the form would, in addition, be
evaluated when the DEFCLASS form was. From reading the rest of the
basenote, I see that it is not, but some kind of forward reference
here would prepare the reader. Also, from the rest of the note, it seems
as if it is implementation dependent as to when the initforms are
evaluated. This is fine, but should be in the concepts section as
well, I think, with a warning that users need therefore to be especially
concerned about initforms which depend on side effects, if they want
to achieve portability.
> When more than one class in the CPL specifies a default value
>form for a given initarg, only the form specified by the earliest such class in
↑↑↑↑↑↑↑↑
>the CPL is used.
Suggest use of "most specific", since "earliest" could be interpreted
either way.
>The primary method for INITIALIZE-INSTANCE is system-supplied and takes care
>of the slot-filling initargs. For each slot (whether local or shared):
>
> - if an initarg was specified or defaulted that fills that slot, its
> value is stored into the slot.
>
> - otherwise, if the slot is uninitialized and it has an initform, the
> initform is evaluated and the result is stored into the slot.
>
> - the duplicate-resolution rules mentioned earlier are obeyed.
Something needs to be said here about the case where a user writes
a :BEFORE method and SETF's the slot there. From the rest of the text,
it sounds as if INITIALIZE-INSTANCE is permitted to clobber that slot.
This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful
for slot initialization. The result requires either that INITIALIZE-INSTANCE
be singled out in a particular way to prohibit :BEFORE methods, or allows
the system to arbitrarily clobber something the programmer has done.
One way out of this dilemma is to simply have the :BEFORE method and the
:AROUND method for INITIALIZE-INSTANCE be reserved for the system.
Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE.
This would leave no places where user defined hooks could be inserted before the
INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods
at their own peril, as is the case with redefining any system defined
method (or function for that matter).
>Do you think it would be worth trying a version of the writeup that uses
>CLtL's terminology, with a simple admonition that a "keyword name" is not
>necessarily a keyword symbol?
Yes, this would be a good idea. I think a case can be made for a semantic
distinction between keyword symbols and keyword arguments. The term
keyword argument is used in Smalltalk as well, where the concept of
keyword symbols does not occur.
4) On method combination types:
> CALL-NEXT-METHOD is supported in :AROUND methods only.
....
>An error is signaled if CALL-NEXT-METHOD is used in a primary method.
In primaries as well???? If so, then we're talking about a major change,
because 87-002 allows it in primaries. Or perhaps this is only for the new
method combination types? If so, then I'd be interested in a reason
for prohibiting method combination in primaries, since it introduces
a major incompatibility between different types of method combination.
5) On :INSTANCE v.s. local:
Either way is OK.
6) On DEFMETHOD syntax changes:
Good.
7) On NEXT-METHODS:
The primary reason is for being able to tell if calling CALL-NEXT-METHOD
would signal an error. I understand Masinter's concern, and wonder if
perhaps it might not be better to handle this with Ken Pitman's error
proposal. Other than finding out whether a call to CALL-NEXT-METHOD is
valid, there isn't much use for the list of next methods, as Masinter
has pointed out.
8) On changing the names of built-in classes:
Good.
9) On SLOT-UNBOUND:
Good.
10) On NO-APPLICABLE-METHOD:
>( no-applicable-method generic-function first-argument &rest
>all-arguments)
I thought we had agreed to get rid of the first argument kludge.
Otherwise, this is the only place in the entire spec where
we're making a distinction between multiple dispatch object
oriented programming and classical object oriented programming.
The user has to go through some additional grief if all the
arguments are passed as an &REST parameter in order to get
forwarding, but I think that forwarding should best be left
to metaobject programmers anyway, since it is, as yet, experimental
(neither PCL nor New Flavors have it). Someone could write a
forwarding metaobject method as:
(defmethod no-applicable-method ( (gf forwarding-generic-function)
&rest all-arguments
)
(apply #'forward-method all-arguments)
)
A user can do something similar with the default method, with
somewhat hairier code.
I think the primary reason people using the default CLOS language
(as opposed to the metaobject protocol) would want all the arguments
anyway is to print a more informative error message.
There are a couple of additional issues which will require specific
longer responses. I'll mail these out today.
jak
∂28-Sep-87 0922 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Amendments requiring additional writing
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 09:22:25 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242911; Mon 28-Sep-87 12:23:22 EDT
Date: Mon, 28 Sep 87 12:23 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Amendments requiring additional writing
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870926-164022-17885@Xerox>
Message-ID: <870928122330.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 26 Sep 87 16:40 PDT
From: Masinter.pa@Xerox.COM
While fixing typep and subtypep to deal with classes seems likely to
preferable to adding instancep and subclassp, attempting to fix type-of
so that it sometimes returns a class and sometimes returns a symbol
seems hopeless, and bad design. type-of is so underconstrained in any
case to be worthless. I think you're better off abandoning it -- e.g.,
implementations can return T if on instances of classes if they need to.
That isn't what we decided to do when we discussed type-of earlier.
The basic principal here is that class objects are legitimate
type-specifiers, they are just not quite as nice to read as symbols.
The fact that there is more than one type-specifier that refers to
exactly the same set of objects is not new to Common Lisp.
Thus making type-of return a class object when there is no meaningful
symbol to return doesn't strike me as making the design of type-of any
worse than it already is. I would be favorable towards a proposal to
remove type-of from Common Lisp entirely, but not towards one to leave
type-of in Common Lisp but declare it broken for CLOS-defined objects.
Aside: this reminds me of an interesting infinite regress. Suppose the
printed representation of an object is #< ... > enclosing the printed
representation of the object's type-of followed by something to try to
distinguish different instances of the type. Now suppose the object's
type is an anonymous class, and the class's type is an anonymous metaclass,
and the metaclass's type is itself. If something special isn't done,
the printed representation starts with an infinite sequence of #< brackets.
Of course this kind of problem is not new, and is easily solved in an
ad hoc way.
The proponents for disallowing careless name->value mappings will likely
be unhappy with the polymorphic typep and subtypep; it might be useful
to be able to lexically determine whether they might be used in a given
program.
That's a good point. Of course it's impossible to determine this lexically
if the relevant functions are used with non-constant arguments, at least if
the data flow and control structure are sufficiently complicated that the
program cannot be statically fully analyzed.
I see two responses to this: the radical response is, this shows how the
type system in Common Lisp is misdesigned, because types are not
first-class objects of their own type. Let's rip out the entire type
system and replace it with a whole new one that's better designed. The
conservative response is, this shows how the type system in Common Lisp
is misdesigned, but let's not rip everything apart now. Instead let's
figure out how to fit a better type system (CLOS) into the existing
language in a smooth way.
At this point I always go for the conservative approach. If I was designing
a new dialect of Lisp, I wouldn't be doing it in the CL-Cleanup committee.
Does anyone else see a linkage between the function-type proposal and
the form for typep/instancep subtypep/subclassp type-of/class-of?
Not me. Do you see a deeper linkage than the one you mentioned, that is
another case of names and referents being allowed to be used interchangeably?
∂28-Sep-87 1006 Moon@STONY-BROOK.SCRC.Symbolics.COM Various Topics Discussed Last Week
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:06:03 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242975; Mon 28-Sep-87 13:06:58 EDT
Date: Mon, 28 Sep 87 13:07 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Various Topics Discussed Last Week
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <16906.559842149@hplabsz>
Message-ID: <870928130706.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 28 Sep 87 09:42:29 MST
From: kempf%hplabsz@hplabs.HP.COM
Comments on excerpts from Jim's message:
1) On SETF:
For purposes of finalizing the spec for the November meeting, I think we
should drop reference to SETF methods.
I think that would be a mistake, because it would simply be postponing the
problem. I'd really like to get this stuff finished soon, and I don't think
it's impossibly difficult. I will mail out a complete proposal for what to
do about SETF later today.
3) On the object creation proposal:
I agree with most of your comments and will update the draft proposal
accordingly.
>The primary method for INITIALIZE-INSTANCE is system-supplied...
Something needs to be said here about the case where a user writes
a :BEFORE method and SETF's the slot there. From the rest of the text,
it sounds as if INITIALIZE-INSTANCE is permitted to clobber that slot.
I think that's what we agreed to at the meeting a couple weeks ago.
This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful
for slot initialization. The result requires either that INITIALIZE-INSTANCE
be singled out in a particular way to prohibit :BEFORE methods, or allows
the system to arbitrarily clobber something the programmer has done.
I agree with you.
One way out of this dilemma is to simply have the :BEFORE method and the
:AROUND method for INITIALIZE-INSTANCE be reserved for the system.
Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE.
This would leave no places where user defined hooks could be inserted before the
INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods
at their own peril, as is the case with redefining any system defined
method (or function for that matter).
I don't see how the methods could be reserved, since there isn't just one;
there's one for every class. However, your proposal is essntially the same
as my proposal to have a specialized kind of method combination for these
generic functions, so that user-defined methods would naturally go only where
they made sense. For some reason that proposal provoked a lot of opposition,
so I dropped it. It could be revived if there is renewed interest. In the
meantime, I won't try to put anything about this into the draft object
creation proposal.
4) On method combination types:
>An error is signaled if CALL-NEXT-METHOD is used in a primary method.
In primaries as well???? If so, then we're talking about a major change,
because 87-002 allows it in primaries. Or perhaps this is only for the new
method combination types?
Yes, this was in the context of method combination types defined by the short
form of define-method-combination.
If so, then I'd be interested in a reason
for prohibiting method combination in primaries, since it introduces
a major incompatibility between different types of method combination.
If you can figure out what it would mean for a primary method in that kind
of method combination to call call-next-method, please make a proposal.
10) On NO-APPLICABLE-METHOD:
>( no-applicable-method generic-function first-argument &rest
>all-arguments)
I thought we had agreed to get rid of the first argument kludge.
Otherwise, this is the only place in the entire spec where
we're making a distinction between multiple dispatch object
oriented programming and classical object oriented programming.
The user has to go through some additional grief if all the
arguments are passed as an &REST parameter in order to get
forwarding, but I think that forwarding should best be left
to metaobject programmers anyway, since it is, as yet, experimental
(neither PCL nor New Flavors have it). Someone could write a
forwarding metaobject method as:
(defmethod no-applicable-method ( (gf forwarding-generic-function)
&rest all-arguments
)
(apply #'forward-method all-arguments)
)
A user can do something similar with the default method, with
somewhat hairier code.
The problem with this is that people want forwarding for "all" generic
functions, not just specially identified ones. I put "all" in quotation
marks because after they have thought about it deeply they usually discover
that there are some generic functions that mustn't forward.
However, I like your suggestion anyway. If we make the arguments to
no-applicable-method be generic-function &rest all-arguments, someone
who wants to do delegation can redefine the default method to call
a new generic function with whatever arguments they want. Not having
that built into CLOS doesn't make it impossible to add on one's own.
∂28-Sep-87 1026 Bobrow.pa@Xerox.COM key argument versus keyword argument
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:26:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 10:26:54 PDT
Date: 28 Sep 87 10:26 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: key argument versus keyword argument
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Mon, 28 Sep 87
09:42:29 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870928-102654-18839@Xerox>
Moon asked:
>Do you think it would be worth trying a version of the writeup
>that uses CLtL's terminology, with a simple admonition that a
>"keyword name" is not necessarily a keyword symbol?
Kempf answered:
Yes, this would be a good idea. I think a case can be made for
a semantic distinction between keyword symbols and keyword
arguments. The term keyword argument is used in Smalltalk as well,
where the concept of keyword symbols does not occur.
I agree with the principal -- but what about calling these "key
arguments" or "&key arguments" and a "key name" is a name that
identifies a key argument.
danny
∂28-Sep-87 1048 Moon@STONY-BROOK.SCRC.Symbolics.COM lambda-list congruence
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:47:51 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243054; Mon 28-Sep-87 13:48:40 EDT
Date: Mon, 28 Sep 87 13:48 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: lambda-list congruence
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870928134842.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is the lambda-list congruence writeup, revised to use CLtL's terminology
for keyword arguments instead of introducing new terminology:
LAMBDA-LIST CONGRUENCE
Changes to Lambda-list Congruence Rules (p.1-20): Rules 1, 2, and 6 remain the
same, except for wording problems, while rules 3-5 need to be replaced to
implement the new rules for &KEY and to fix the interaction among &KEY, &REST,
and &ALLOW-OTHER-KEYS. The new rules for congruence are the following:
These rules define the congruence of a set of lambda-lists, including the
lambda-list of each method for a given generic function and the lambda-list
specified with DEFGENERIC, if present. For (SETF generic) methods, these
rules apply to the effective lambda-list produced by combining the two
specified lambda-lists according to the rules on page nnn.
1. Each lambda-list must have the same number of required parameters.
2. Each lambda-list must have the same number of optional parameters.
Each method can supply a different default for an optional parameter.
3. If any lambda-list uses &REST or &KEY, each lambda-list must use one or
more of these.
4. If the DEFGENERIC uses &KEY, each method must accept all of the
keyword names mentioned after &KEY in DEFGENERIC, either by accepting
them explicitly, by specifying &ALLOW-OTHER-KEYS, or by specifying &REST
but not &KEY. Each method can accept additional keyword arguments of its
own. The checking of the validity of keyword names is not done in each
method; instead it is done in the generic function.
5. The use of &ALLOW-OTHER-KEYS need not be consistent across lambda-lists.
If &ALLOW-OTHER-KEYS is used in any lambda-list, then any keyword arguments
may be used in the call to the generic function.
6. The use of &AUX need not be consistent across methods.
∂28-Sep-87 1107 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: draft of built-in method combination types
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:07:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id af22832; 28 Sep 87 13:11 EDT
Received: from ti-csl by RELAY.CS.NET id aj05242; 28 Sep 87 12:59 EDT
Received: from Jenner by tilde id AA05968; Mon, 28 Sep 87 11:16:19 CDT
Message-Id: <2768832864-16341119@Jenner>
Date: Mon, 28 Sep 87 11:14:24 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: draft of built-in method combination types
In-Reply-To: Msg of Wed, 23 Sep 87 07:27 EDT from "Sonya E. Keene" <skeene@SCRC-STONY-BROOK.ARPA>
Date: Wed, 23 Sep 87 07:27 EDT
From: "Sonya E. Keene" <skeene@SCRC-STONY-BROOK.ARPA>
Subject: draft of built-in method combination types
A primary method has the name of the method combination type as its
sole qualifier. For example, the method combination type AND
recognizes methods whose sole qualifier is AND; these are primary
methods.
I thougt about it some more and found two disadvantages in qualifying
primary methods:
When one wants to change the method-combination type (from NCONC to
APPEND), one has to change the qualifiers of all the primary methods in
the source files.
Automatic method generators will have to know about the method
combination type.
∂28-Sep-87 1117 RPG Shared/local;class/instance
To: common-lisp-object-system@SAIL.STANFORD.EDU
I believe we ought to pick a consistent set of names for these :allocation
types and keywords. I believe that the pair shared/local makes a little
more sense in that I wouldn't expect novices to know or remember that a
class-allocated slot would be visible to the instances and hence shared.
I believe that things like :dynamic or :procedure, to pick up on Danny's
suggestion, are of a nature orthogonal to :shared/:local, because the
latter speaks of the scope of the slot rather than of any implementation
technique. Continuing in this vein, it seems that many :allocation
keywords ought to be allowed: why cannot a :shared slot be :dynamic
as well?
Shall we extend the :allocation option to be either a single allocation-type
or a list of them?
-rpg-
∂28-Sep-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM key argument versus keyword argument
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:20:42 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243109; Mon 28-Sep-87 14:19:48 EDT
Date: Mon, 28 Sep 87 14:19 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: key argument versus keyword argument
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870928-102654-18839@Xerox>
Message-ID: <870928141948.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Sep 87 10:26 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon asked:
>Do you think it would be worth trying a version of the writeup
>that uses CLtL's terminology, with a simple admonition that a
>"keyword name" is not necessarily a keyword symbol?
Kempf answered:
Yes, this would be a good idea. I think a case can be made for
a semantic distinction between keyword symbols and keyword
arguments. The term keyword argument is used in Smalltalk as well,
where the concept of keyword symbols does not occur.
I agree with the principal -- but what about calling these "key
arguments" or "&key arguments" and a "key name" is a name that
identifies a key argument.
That seems like a raesonable idea. At this point, as far as I am
concerned I would rather follow CLtL's terminology, imperfect as it
is, than spend time trying to invent new terminology. My efforts
on the latter haven't been successful so far, and I'd rather work
on finishing CLOS. However, if Common Lisp comes up with better
terminology, we can certainly adjust the description of CLOS to match.
∂28-Sep-87 1114 Moon@STONY-BROOK.SCRC.Symbolics.COM Revised draft of object creation proposal
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:13:33 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243088; Mon 28-Sep-87 14:14:24 EDT
Date: Mon, 28 Sep 87 14:14 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Revised draft of object creation proposal
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870928141430.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
This version differs from the previous one I mailed out only in some
small corrections based on comments received in the mail. The terminology
has been changed back from "named argument" to "keyword argument."
It may be about time to start converting this to the text that will go
into the specification document. Any more comments first?
Draft of, and notes toward, a new object creation proposal based on
CLOS subcommittee discussions July 2, 1987. Updated based on Sep 17-18
1987 working group meeting. Updated based on mail received up to Sep 28,
and converted back to CLtL terminology for keyword arguments.
-foo- means the word foo in italics. FOO means the word foo in boldface.
PREREQUISITES
This proposal assumes keyword arguments to methods work as described in the
accompanying lambda-list congruence proposal.
The proposal assumes CL-Cleanup issue KEYWORD-ARGUMENT-NAME-PACKAGE, which
stated that the names of &key arguments do not have to be keyword symbols.
The terminology of CLtL is used for discussing keyword arguments, but it
should be understood that keyword names are not necessarily symbols in
the keyword package; that's just a default convention.
CONCEPTS TO BE ADDED TO 87-002
-initarg-. An initarg (initialization argument) is a keyword argument that
can be used to control object creation and initialization. The &key arguments
to MAKE-INSTANCE are initargs. It is often convenient to use keyword symbols
to name initargs, but the name of an initarg can be any symbol, including NIL.
-initarg list-. An initarg list (initialization argument list) is a list of
alternating initarg names and values. Its structure is identical to a
property list and also identical to the portion of an argument list processed
for &key parameters. As in those lists, if an initarg name appears more than
once in an initarg list, the leftmost occurrence supplies the value and the
remaining occurrences are ignored. The arguments to MAKE-INSTANCE, after the
first, are an initarg list. As in an &key argument list, :ALLOW-OTHER-KEYS
can appear in an initarg list, and if its value is non-NIL, error-checking of
initarg names is disabled.
-slot-filling initarg-. An initarg associated with a slot. If the initarg
has a value in the initarg list, the value is stored into the slot of the
newly-created object, overriding any initform associated with the slot. A
single initarg can fill more than one slot. A slot-filling initarg that
fills a shared slot stores its value into the shared slot, replacing any
previous value.
-method-implemented initarg-. An initarg associated with a method. When
an object is created, the method is called with the initarg's value as an
argument and the method uses the value in any way it likes. If the initarg
has no value in the initarg list, the method's lambda-list supplies a
default value. A single initarg can be implemented by more than one
method. An initarg can be both slot-filling and method-implemented.
CHANGES TO 87-002 FEATURES
DEFCLASS gets a new :INITARG slot option, which is followed by a symbol.
The symbol becomes the name of a slot-filling initarg for this class.
This slot option can appear any number of times.
DEFCLASS gets a new :DEFAULT-INITARGS option, which is followed by a list of
alternating initarg names and default-initarg forms. If one of these initargs
does not appear in the initarg list supplied to MAKE-INSTANCE, the
corresponding default-initarg form is evaluated, then the initarg name and the
form's value are added to the end of the initarg list. The form is evaluated
every time it is used. The lexical environment in which this form is
evaluated is the lexical environment in which DEFCLASS was evaluated. The
dynamic environment is the dynamic environment in which MAKE-INSTANCE was
called. The appearance of a symbol as an initarg name in a :DEFAULT-INITARGS
option does not make that symbol a valid initarg name for the class.
The :DEFAULT-INITARGS option may be specified more than once.
[Should the name of this option be :DEFAULT-INITARGS or :DEFAULT-INITARG ?]
Method-implemented initargs are defined simply by defining a method for
INITIALIZE-INSTANCE or ALLOCATE-INSTANCE. The keyword name of each keyword
parameter specifier in the method's lambda-list becomes a method-implemented
initarg for all classes for which this method is applicable.
Initarg inheritance: The effective set of slot-filling initargs for a class C
is the union of the slot-filling initargs defined by C and its superclasses.
The effective set of method-implemented initargs for a class C is determined
by method inheritance.
Default-initargs inheritance: The set of initargs of C that have default value
forms is determined by the union of the :DEFAULT-INITARGS options of C and its
superclasses. When more than one class in the CPL specifies a default value
form for a given initarg, only the form specified by the most specific such
class in the CPL is used.
Rules when initargs are duplicated in various ways:
The :INITARG slot-option may be specified more than once for a given slot.
A single initarg can initialize more than one slot if the same initarg name
appears in more than one :INITARG slot-option.
It is valid for a given initarg name to be defined more than once as a
slot-filling initarg, as a method-implemented initarg, or both.
If two initargs that initialize the same slot, with the same or different
names, are given in the arguments to MAKE-INSTANCE, the leftmost of these
initargs in the initarg list prevails.
If two different initargs that initialize the same slot have default values,
and neither is given explicitly in the arguments to MAKE-INSTANCE,
the initarg that appears in a :DEFAULT-INITARGS slot-option in the most
specific class prevails, or if they appeared in the same class, the one whose
mention in :DEFAULT-INITARGS is leftmost in the DEFCLASS form prevails.
Defaulted initargs are appended to the end of the initarg list in this order.
If there are two different initargs that initialize the same slot, and one
was given explicitly in the arguments to MAKE-INSTANCE while the other was
defaulted via :DEFAULT-INITARGS, the explicit one prevails. (This rule is
implied by the two preceding rules, but it seems worth drawing attention to.)
If a slot has both an :INITFORM and an :INITARG slot-option, and the
slot-filling initarg is defaulted via :DEFAULT-INITARGS, the initform is not
used and is not evaluated.
An illustrative example of the above rules:
(defclass a () ((x :initarg a)))
(defclass b (a) ((x :initarg b))
(:default-initargs a 1 b 2))
FORM INITARG LIST CONTENTS OF X SLOT
(make-instance 'b) (a 1 b 2) 1
(make-instance 'b 'a 3) (a 3 b 2) 3
(make-instance 'b 'b 4) (b 4 a 1) 4
(make-instance 'b 'a 1 'a 2) (a 1 a 2 b 2) 1
Note: nothing is guaranteed about the order of evaluation of default-initarg
forms and initforms. If there are dependencies among these forms, you should
be using INITIALIZE-INSTANCE methods instead. In most programs, the initforms
and default-initarg forms are either constants or simple forms that construct
new objects; forms with side-effects are permitted, but are not typically used.
NEW FUNCTIONS TO BE ADDED
In this section, I have only sketched each function, for the sake of brevity.
Full writeups can be constructed once the overall framework has been agreed
upon. Functions are in alphabetical order, in three sections at three protocol
levels. The breakdown between the second and third levels may be changed. By
coincidence, all functions listed except SLOT-BOUNDP and SLOT-MAKUNBOUND are
generic and expected to specialize on their first argument.
>>> Tools used for simple object-oriented programming:
(INITIALIZE-INSTANCE instance &key &allow-other-keys)
MAKE-INSTANCE calls this with the freshly-created instance, any initargs that
were supplied to MAKE-INSTANCE, and any defaulted initargs. Users define
methods for this to create method-implemented initargs. Typically,
user-defined methods are :AFTER methods, however that is not a requirement.
The primary method for INITIALIZE-INSTANCE is system-supplied and takes care
of the slot-filling initargs. For each slot (whether local or shared):
- if an initarg was specified or defaulted that fills that slot, its
value is stored into the slot. (This is true even if a :BEFORE method
has modified the slot.)
- otherwise, if the slot is uninitialized and it has an initform, the
initform is evaluated and the result is stored into the slot.
- the duplicate-resolution rules mentioned earlier are obeyed.
An implementation is permitted to optimize initforms that neither produce nor
depend on side-effects, by evaluating them and storing them into slots before
running any INITIALIZE-INSTANCE methods, rather than handling them in the
primary INITIALIZE-INSTANCE method. This might be implemented by having the
ALLOCATE-INSTANCE method copy a prototype instance. This means that :BEFORE
and :AROUND methods for INITIALIZE-INSTANCE cannot rely on all the slots being
uninitialized at the beginning.
An implementation is permitted to optimize default value forms for slot-filling
initargs by not actually consing the complete initarg list, when the only
method that would see the complete list is the system-supplied primary method,
e.g. when no other methods use &REST. In this case default value forms can be
treated like initforms. This has no visible effects other than a performance
improvement.
(MAKE-INSTANCE class &key -initargs-...) => instance
Users call this function to create objects. Class can be either a class or
the name of a class. Meta-users can define new methods for MAKE-INSTANCE
to replace the object-creation protocol.
(SLOT-BOUNDP instance slot-name) => boolean
Allows writing INITIALIZE-INSTANCE :AFTER methods that only initialize slots if
they haven't been initialized already.
(SLOT-MAKUNBOUND instance slot-name) => instance
Restores a slot to the uninitialized condition.
>>> Functions underlying the tools
It is undefined what happens if you modify the values returned by any
of the functions in this section. It is permitted, but not required,
for an implementation to return values that share with internal data
structures. Some of these functions will be SETF'able; which ones
remain to be determined.
(CLASS-ALL-INITARGS class) => list of initarg names, including inherited
ones. This is (REDUCE #'UNION (MAPCAR #'CLASS-DIRECT-INITARGS cpl)).
(CLASS-DIRECT-INITARGS class) => list of initarg names. This works by
computing the applicable methods for ALLOCATE-INSTANCE and for
INITIALIZE-INSTANCE and examining their lambda-lists (using
METHOD-KEYWORD-NAMES), then combining that with the class's list of
slot-filling initargs.
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function default-value-form)...)
(CLASS-DIRECT-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function default-value-form)...)
This reflects the :DEFAULT-INITARGS option. Default-value-form is the form
that was originally specified, and is retained purely for explanatory
purposes. default-value-function is what gets actually called; its effect is
equivalent to enclosing default-value-form in the appropriate lexical
environment. Default-value-function takes no arguments.
(CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
This reflects the :INITARG slot-option.
(COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods
(METHOD-KEYWORD-NAMES method) => list of symbols or &ALLOW-OTHER-KEYS,
indicating the keyword names of the keyword parameter specifiers in
the method's lambda-list. The result is the symbol &ALLOW-OTHER-KEYS
instead of a list if the method's lambda-list contains that symbol.
>>> Meta-object functions
(ALLOCATE-INSTANCE class &key &allow-other-keys) => instance
Meta-users can replace the system-supplied, implementation-dependent method
for this. Any keyword arguments accepted by applicable ALLOCATE-INSTANCE
methods become valid initargs.
(CHECK-INITARGS class initarg-list)
Meta-users could replace the system-supplied method that implements the
normal rules for initarg validity.
(DEFAULT-INITARGS class initarg-list) => initarg-list
The system-supplied method implements the :DEFAULT-INITARGS class option
by appending initargs that do not appear in initarg-list to the end
of the returned list. The initarg-list supplied as an argument is not
modified. The order of initargs appended to the list is determined by
the duplicate-initarg rules listed earlier.
(FINALIZE-INHERITANCE class &key slots methods initargs)
This is called by the system at least once before a class is instantiated, and
is called again whenever anything relevant changes. System-supplied methods
for this conspire with methods for CHECK-INITARGS, etc., to make MAKE-INSTANCE
faster. Users with their own optimization needs can add methods for this
generic function that will precompute things based on inherited information,
and update the precomputed information whenever anything changes.
The :slots, :methods, and :initargs arguments are booleans that are true
when the specified type of inheritance needs to be recomputed.
PROCEDURAL DEFINITION OF MAKE-INSTANCE
MAKE-INSTANCE behaves as if it was defined as follows, except that certain
optimizations are permitted, as detailed below and in the description of
INITIALIZE-INSTANCE.
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
Optimization is possible, including inlining and constant-folding of method
lookup and method bodies, provided that the programming environment either
prohibits redefining these methods or updates everything when they are
redefined. A possible example implementation would be that MAKE-INSTANCE has
a separate method for every class, which is automatically written and compiled
by the system.
This optimization relies on the FINALIZE-INHERITANCE generic function and some
unpublished slots of STANDARD-CLASS.
Because of optimization, methods for the generic functions listed may not
actually be called on every call to MAKE-INSTANCE, or may not receive
exactly the arguments that would be expected. For example, CHECK-INITARGS
may actually be called before DEFAULT-INITARGS rather than after, if it has
already been determined that the default initargs will pass CHECK-INITARGS.
Additional explicit details of permissible optimization will need to be set
forth.
MEETING OF STATED DESIGN GOALS
Lexical proximity of concepts--the declaration of an initarg as valid,
the specification of what it does, and the default if it is not supplied
are all together, in a slot specifier or in a method lambda-list.
Simple ways to do simple things--slot-filling initargs don't require the
user to write any code. Method-implemented initargs work just like
ordinary function arguments as far as the user is concerned.
Minimal number of new languages--the only addition to Common Lisp is
a mildly complicated rule for how &KEY lambda-lists of methods do
validity checking.
Ability to do everything at some level--the underlying procedural level
is available. Functions to access all the direct and inherited
information are documented.
Underlying mechanism is exposed so user can use it for other things, rather
than abusing instance creation as the only way to access the mechanism--the
combination of &KEY, METHOD-KEYWORD-NAMES, COMPUTE-APPLICABLE-METHODS, and
FINALIZE-INHERITANCE provides everything the user needs.
∂28-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Shared/local;class/instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:54:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 11:55:01 PDT
Date: 28 Sep 87 11:49 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Shared/local;class/instance
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Sep 87
11:17 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870928-115501-19131@Xerox>
I believe we ought to pick a consistent set of names for these
:allocation types and keywords. I believe that the pair
shared/local makes a little more sense in that I wouldn't expect
novices to know or remember that a class-allocated slot would be
visible to the instances and hence shared.
I can't imagine them knowing anything else after they read the
documentation once. And it is more important to have only a single set
of words than to have a simple property of the current pair used as an
alternative. So once again I vote for instance/class rather than
local/shared.
I believe that things like :dynamic or :procedure, to pick up
on Danny's suggestion, are of a nature orthogonal to
:shared/:local, because the latter speaks of the scope of the slot
rather than of any implementation technique. Continuing in this
vein, it seems that many :allocation keywords ought to be allowed:
why cannot a :shared slot be :dynamic as well?
I answered your last question earlier -- referring to the use of dynamic
as an implementation tradeoff that is not relevant for shared slots.
Shall we extend the :allocation option to be either a single
allocation-type or a list of them?
I don't think we need yet another programming language (i.e. a method
for compostion) for this option -- simple extensibility is enough. I
would rather use the symbol that specifies the option as our means of
referring to the type of slot, rather than another word that refers to a
property of that kind of slot.
∂28-Sep-87 1254 kempf%hplabsz@hplabs.HP.COM Re: Exact type
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 12:54:12 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 12:53:34 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 28 Sep 87 13:54:30 pdt
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Exact type
X-Mailer: mh6.5
In-Reply-To: Your message of Tue, 22 Sep 87 11:25:11 -0500.
<2768315111-8803361@Jenner>
Date: Mon, 28 Sep 87 13:54:27 MST
Message-Id: <19989.559857267@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>x is of exact-type X if it verifies:
>Let Y be a type such as (SUBTYPEP X Y) is true,
>then (TYPEP x Y ) is false.
Yes, except I think what you want the compiler to verify is
"If for all such Y, (TYPEP x Y) is false, then x is of EXACT-TYPE X".
>But allowing the other COMMON subtypes would makes programs non portable:
>The list of subtypes of a type is implementation dependent. We say (page
>1-14) that individual implementation can add additional subclass
>relationships as long as they don't violate CLtL.
But the subtype relationships in CLtL must still hold. Thus, any
importabilities will be the result of importabilites in the Common
Lisp type system, not in the CLOS addition. Reading the rules on
pg. 33-35, it's difficult to discern importabilities, but, talking
to Gregor (who has some experience in this area), they do exist.
However, I think the place to address the problem is to tighten up
the Common Lisp type system, not restrict EXACT-TYPE.
In addition, declarations in Common Lisp have a certain flavor of
implementation dependency to them anyway, as this quote from CLtL,
pg. 153 should indicate:
With one exception, declarations are completely optional
and correct declarations do not affect the meaning of a
correct program. The exception is that SPECIAL declarations
_do_ affect the interpretation of variable bindings and
references, and so _must_ be specified where appropriate. All
other declarations are of an advisory nature, and may be
used by the LISP system to aid the programmer by performing
extra error checking or producing efficient compiled code.
....
Note that it is considered an error for a program to violate
a declaration (such as a TYPE declaration), but an implementation
is not required to detect such errors (though such detection,
where feasible, is to be encouraged).
While I don't particularly agree with this policy, I think that it gives
implementations so much latitude already that restricting EXACT-TYPE would
be inappropriate.
However, if anyone else feels strongly about this, or has a good counter-
argument, I'd be willing to change the specification.
jak
∂28-Sep-87 1336 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 13:36:18 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 13:36:54 PDT
Date: 28 Sep 87 13:34 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Amendments requiring additional writing
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 25 Sep 87 21:41 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870928-133654-19356@Xerox>
A slightly modified version of Moon's pararaph to remove references to
change-class
1-11: Replace the last paragraph with the following two paragraphs:
If in the new version of the class there is an instance slot of the
same name as any slot in the old version of the class, the value of
that slot will be the same in both instances. This means that if
the slot has a value, the value returned by {\bf slot-value} after
the class is redefined {\bf eql} to the value returned by {\bf
slot-value} before the class is redefined. Similarly, if the slot
was uninitialized, it remains uninitialized.
This is fine so far. But the following is problematic.
At the moment a class is redefined, if the new version of the
class contains a shared slot of the same name as any shared slot in
the old version of the class, the value of that slot will be the
same in both.
Should this be true? Will changing the context of the defclass form not
effect the value of the class slot. I think this is a mistake.
Redefining the class should set the value of the class slots, and
whether that value is EQL or not must depend on the evaluation form and
context.
I also have a problem with:
If in the new version of the class there is a shared slot of
the same name as any local slot in the old version of the class,
that shared slot is initialized to the value of the corresponding
{\bf :initform} option of the new class, or remains uninitialized
if the new version of the class does not specify or inherit the
{\bf :initform} option for that slot. Shared slots are not
affected by the updating of an instance.
This again seems mistaken for me. What value should go in the new
shared slot -- that is, from which particular instance will it be set.
I think the correct paragraph would read:
If in the new version of the class there is a class slot of the
same name as any instance slot in the old version of the class,
that class slot is initialized by the redefinition of the class,
and is not affeced by the value of any slot in any of the
instances. If there is an instance slot in the new definition of
the class that is the same name as a class slot in the old version
of the class, then on updating, the value of each instance slot is
given the same (EQL) value as the that in the old class slot. If
the class slot in the old version of the class was uninitialized,
then the instance slots in the new instances are initialized as if
they were new slots in the instance.
∂28-Sep-87 1355 Moon@STONY-BROOK.SCRC.Symbolics.COM fixing our problems with setf
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 13:54:51 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243389; Mon 28-Sep-87 16:55:16 EDT
Date: Mon, 28 Sep 87 16:55 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: fixing our problems with setf
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870920-190342-9834@Xerox>,
<870921-091049-10309@Xerox>,
<870921163510.2.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<2768308570-8410382@Jenner>,
<16906.559842149@hplabsz>
Message-ID: <870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
The goal is to unify the handling of "setf functions" with the handling
of regular functions, so we don't need a proliferation of -setf versions
of defmethod, defgeneric, ensure-generic-function, fboundp, generic-labels,
with-added-methods, etc. The major issue is that Common Lisp has not seen
a need to do this already, so the onus falls on CLOS. In addition, we
ran into difficulty with confusion between the idea of associating a
function name with a function object (in our case, a generic function
object), and the idea of associating a way to setf a function with that
function. This proposal unifies those ideas.
I believe the following proposal neatly solves the problem.
Add to Common Lisp the same concept of "setf functions" that we are
already introducing in CLOS. Right now, Common Lisp only has "setf
macros", which are defined by define-setf-method and both forms of
defsetf. I draw the distinction because a "setf macro" is something
that produces code (or other specifications, as in define-setf-method)
which, when evaluated, will perform the effect of an invocation of setf,
while a "setf function" is something that is called to perform directly
the effect of an invocation of setf.
As with regular functions, associated with any given name you can have a
setf function or a setf macro, but not both. This means that one does
not define a setf function (with defmethod or defgeneric) and also call
defsetf. The mere act of defining the setf function is enough to tell
setf what to do.
Since setf functions are in a separate, but parallel, namespace from
regular functions, we need a way to name them. The simplest way is to
allow a list (setf -name-) to be used as the name of the setf function
that is called to perform the effect of (setf (-name- ...) ...). The
following functions, macros, and special forms defined in CLtL need to
be enhanced to accept such lists where they now accept symbols as
function names:
compile
defun
disassemble
documentation
fboundp
flet
fmakunbound
function
labels
symbol-function and setf of symbol-function
trace
untrace
The following functions, macros, and special forms defined in CLOS need
to be enhanced in the same way:
defgeneric
defmethod
ensure-generic-function
generic-flet
generic-labels
with-added-methods
defmethod-setf and defgeneric-setf need to be removed.
Note that in Common Lisp, setf macroexpansion is an operation on
function names, not on functions. It differs from some dialects of
Scheme, such as T, in this respect. This proposal does not attempt to
change that.
Note that I do not propose to introduce lexically local setf macros,
that is, a cross between defsetf and macrolet. This does not appear to
be logically necessary. If someone else wants this, it would certainly
not be hard to do. The main issue is whether all three ways of defining
lexically global setf macros need local counterparts. I also do not now
propose to codify the definition of global setf macros, for example to
say that (macro-function '(setf foo)) returns an expander function that
takes two arguments and returns five values.
The next issue is what to do about the lambda-list of a setf-function.
We already agreed on what is the lambda-list in the expansion of
(defun (setf foo) ...) into
(setf (symbol-function '(setf foo)) #'(lambda ...)). Specifically,
#'(setf foo) takes one more required argument than #'foo, and the last
required argument is the new value to be stored.
The issue is whether certain function-defining macros should have a
special syntax with two lambda-lists when defining a setf function, or
should use their normal syntax. The macros in question are defun, flet,
labels, defgeneric, defmethod, and the :method option to defgeneric,
generic-flet, generic-labels, and with-added-methods. In favor of two
lambda-lists is that it's easier for the programmer to see which
parameter is bound to the new value to be stored. In favor of one
lambda-list is syntactic consistency between setf functions and regular
functions. At the meeting two weeks ago, we favored two lambda-lists,
but I now believe that that was a mistake. The rule that the new value
is the last required argument should not be at all difficult for
programmers to understand. Syntactic consistency is important.
The remaining issue is a scoping issue. We have introduced lexically
local setf functions, where before Common Lisp only had lexically global
setf macros. Thus the namespace of setf operators has been extended to
have a lexical component, just like the namespace of regular operators.
(Recall that "operator" means the union of functions, macros, and
special forms). Regular functions and setf functions naturally come in
pairs, but since they are defined separately we have to specify what
happens in various cases where only one is defined at a given lexical
contour.
The simplest solution would be to say that (setf (-foo- ...) ...) ignores
the scope of the name -foo- when considering how to setf it. However, this
solution has already been ruled out by the Cleanup committee's resolution
of issue GET-SETF-METHOD-ENVIRONMENT. Specifically inside the scope of
a macrolet of foo, the expansion of (setf (foo ...) ...) proceeds by
calling the macrolet expander, regardless of whether there is a globally
defined setf macro for foo. Similarly, inside the scope of a flet of foo,
(setf (foo ...) ...) is invalid.
To be consistent with this, I propose a suite of three rules for the
behavior of local function defining forms (flet, generic-flet,
generic-labels, labels, macrolet, and with-added-methods):
(1) A local function definition of the name foo implicitly shadows the
scope of a global setf macro definition for foo.
(2) A local function definition of the name foo implicitly shadows the
scope of any enclosing function definition of (setf foo). When the same
function defining form defines both foo and (setf foo), the scopes of
the two names are equal regardless of their order of appearance in the
function defining form.
(3) A local function definition of the name (setf foo) does not change
the scope of any enclosing function definition of foo.
with-added-methods may require a special rule, because of its unusual
half-shadowing semantics. I'm inclined to ignore this and say that
(with-added-methods ((foo ...)) ...) shadows any enclosing definition
of (setf foo), just like generic-labels.
Example (for Patrick):
(defmethod (setf subseq)
((sequence vector) start (new-value vector) &optional end)
(unless end (setq end (length sequence)))
(setq end (min end (+ start (length new-value))))
(do ((i start (1+ i))
(j 0 (1+ j)))
((= i end) new-value)
(setf (aref sequence i) (aref new-value j))))
If this meets with general approval I will recast this for the Cleanup
committee.
∂28-Sep-87 1407 Moon@STONY-BROOK.SCRC.Symbolics.COM Various Topics Discussed Last Week
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:06:58 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243408; Mon 28-Sep-87 17:05:34 EDT
Date: Mon, 28 Sep 87 17:05 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Various Topics Discussed Last Week
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <16906.559842149@hplabsz>
Message-ID: <870928170524.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 28 Sep 87 09:42:29 MST
From: kempf%hplabsz@hplabs.HP.COM
2) On blocks in methods:
I agree that Alternative 1 would be best. Users who want something
different can either use a :AROUND method, as Moon suggested, or
program their own generic function dispatching function, using
the metaobject protocol.
Since we all seem to be agreed on this, I added the following to my
clos-decisions file, which can be used as a resource to make sure
we don't forget to document this decision:
2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded
by an implicit block named -name-, if that is a symbol, or -name1-, if
-name- is (SETF -name1-), by analogy with DEFUN. The same applies to
methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET,
GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around
the body of a method defined by the :METHOD option to GENERIC-FUNCTION.
Dissenters speak now.
7) On NEXT-METHODS:
The primary reason is for being able to tell if calling CALL-NEXT-METHOD
would signal an error. I understand Masinter's concern, and wonder if
perhaps it might not be better to handle this with Ken Pitman's error
proposal. Other than finding out whether a call to CALL-NEXT-METHOD is
valid, there isn't much use for the list of next methods, as Masinter
has pointed out.
I have no real opinion on this, but we could change this to NEXT-METHOD,
which returns the method object that CALL-NEXT-METHOD would call if
there is one, and returns NIL if CALL-NEXT-METHOD would signal the
no-more-methods error. Then we wouldn't have to worry about the
implications of consing, rplac'ing, and looking at the list.
∂28-Sep-87 1419 Bobrow.pa@Xerox.COM Re: fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:18:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 14:19:13 PDT
Date: 28 Sep 87 14:18 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: fixing our problems with setf
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 28 Sep 87 16:55 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870928-141913-19460@Xerox>
As with regular functions, associated with any given name you
can have a setf function or a setf macro, but not both. This means
that one does not define a setf function (with defmethod or
defgeneric) and also call defsetf. The mere act of defining the
setf function is enough to tell setf what to do.
Does this mean that if I do a
(defsetf foo ...)
(defun (setf foo) ...)
then the setf macro has been undone. (I hope so). And similarly in the other direction.
danny
∂28-Sep-87 1451 Bobrow.pa@Xerox.COM Re: Redefining Classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:51:03 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 14:51:31 PDT
Date: 28 Sep 87 14:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Redefining Classes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 24 Sep 87 23:35 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
Message-ID: <870928-145131-19538@Xerox>
If the redefinition of a class causes the structure of
its instances to be different...
I think we're going to have to define this more precisely. I
see two options:
(1) Adding or removing an instance slot definitely changes the
structure, and some other operations may also change the structure,
depending on the implementation.
(2) The structure changes if and only if the value of
(class-all-instance-slot-names class) is not EQUAL to its previous
value. I made up the function name class-all-instance-slot-names,
but you get the idea. Note how class-all-slot-names won't work.
The big difference between option 1 and option 2 is that with
option 2, a given sequence of defclass forms will produce exactly
the same sequence of calls to make-instances-obsolete in all
implementations.
I'm inclined to option 2, because it is more precise, but I'm
worried that this might rule out some implementation possibility.
Also, for this to be meaningful and portable, we have to define the
exact order of slots produced by slot inheritance, which is not
something we've had to specify before now.
I agree with you on the choice of how one specifies this. In the
metaobject protocol, we currently have a generic function
all-slot-names class &optional allocation
which returns a list of slot names.
The allocation argument can be an allocation symbol (e.g. :instance,
:class), or nil meaning names for slots regardless of allocation. For
allocation = :instance, the list returned by the implementation should
be one that is ordered by the implementation. Thee is no method to
specify the order of instance slots in the instance. An implementation
is free to decide on the layout (e.g. so that reversing two slot names
in a defclass form does not necessarily obsolete the instances). By
documenting all-slot-names, we can avoid the specification of the
ordering rules, and still provide a specification of what we mean.
I have two problems with [update-obsolete-instance].
The easy problem is that I
don't like the name update-obsolete-instance, because the instance
doesn't really seem obsolete to me. One idea is to take an analogy
to class-changed and call it class-redefined. In Flavors we call
it transform-instance, but it doesn't have quite the same
semantics. It's likely that someone can think of a better name
than any of these.
We could call it update-from-obsolete-instance, or
conform-instance-to-class. Since it takes ans instance as an argument,
I don't like names like class-redefined -- which seems to focus on the
class.
Much more important, I can't implement the specification that
the slots are initially uninitialized and then they are filled in
from values saved in a property list. There are two problems, one
obvious and one subtle. The obvious problem involves slots that
were unbound originally; since there is no Lisp value that means
"unbound", there is nothing that can be put into the property list
for these slots. But if we don't put any entry in the property
list, then the desired feature that the method can tell which slots
were added or removed is lost; these slots look like they were
added, even though they weren't.
We could designate such a value (make it be the value of a globally
accessible variable). Then putting such a value in a slot would be
equivalent to making it unbound. I can hear the ARGHHH from here, but
it does make accessible something that we are having to make
programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste
(and I could be convinced on this fairly easily), why is it you could
not implement this -- is there a particular tradeoff that you are not
being explicit about?
Also, the default method you
mention below will put the :initform value into these previously
unbound slots, which seems wrong. "Unbound" should not be
confounded with "nonexistent."
I feel that making unbound slots be initialized is a feature, not a bug.
One good reason to make a class obsolete may be to cause formerly
unbound slots to be initialized. That is, one could redefine a class,
adding an initform option, and be sure that any instances that had that
slot unbound would now have it bound to the specified value.
The subtle problem involves some language extensions that we
have, allowing slots to have contents that cannot be expressed as
Lisp values in a property list. For instance, there is a mechanism
similar to Prolog logic-variables which allows two slots to be
linked together. This linkage has to be preserved in the face of
class redefinition.
Can such linked values only be used inside of objects, and not within
lists? I though inivisible pointers can be used anywhere. I don't
understand what the assumptions underlying this extension are.
For these reasons, I believe it is better to specify that the
slot values are conveyed from the old structure of the instance to
the new structure by the low-level implementation, not by a
user-replaceable method. Thus when the generic function
update-obsolete-instance is called, all slots that existed in the
old class definition, and existed as instance slots in the new
class definition, already have their values, as the same low-level
bits. I can't see any need for even a meta-user to replace this
with something else.
Without the reasons given above, I still like this proposal as well as
the one I wrote up. It supports the proposed model at a better level.
I suggest conveying the desired information directly, rather
than trying to be clever: Give update-obsolete-instance four
arguments:
the instance
a list of the names of all added slots
a list of the names of all deleted slots
a property list giving the values of all deleted, bound slots
I actually think this is fine. But I would also say that the underlying
implemention also initializes existing slots that were unbound, using
the initforms in the class, if any.
I would say the default method initializes only the
newly added slots.
Fine I will write it up this way.
Because update-obsolete-instance is user code, its
operation can be seen by the user; but the model that CLOS
supports is that as far as the user can tell, all the existing
instances of a class are updated as soon as the class
redefinition happens. This implies that the user must define a
method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing
instances (for example, to method call or slot access time),
but users should never be able to see the untransformed
instance.
We're going to have to specify this a little more precisely, I
suspect. We should specify when is the latest time that an
implementation can call update-obsolete-instance, and then say that
it is permitted to call it any time earlier (after the class has
been redefined). I now believe that the latest time can simply be
the time any of the four slot access and modification functions (or
internal equivalent) is called, in spite of all the flaming against
this we engaged in while discussing Danny's proposal at the meeting
last week.
Agreed.
∂28-Sep-87 1546 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Amendments requiring additional writing
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:46:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243539; Mon 28-Sep-87 18:43:00 EDT
Date: Mon, 28 Sep 87 18:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Amendments requiring additional writing
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870928-133654-19356@Xerox>
Message-ID: <870928184306.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Sep 87 13:34 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
A slightly modified version of Moon's pararaph to remove references to
change-class
1-11: Replace the last paragraph with the following two paragraphs:
If in the new version of the class there is an instance slot of the
same name as any slot in the old version of the class, the value of
that slot will be the same in both instances. This means that if
the slot has a value, the value returned by {\bf slot-value} after
the class is redefined {\bf eql} to the value returned by {\bf
slot-value} before the class is redefined. Similarly, if the slot
was uninitialized, it remains uninitialized.
You're right, I spazzed in editing and shouldn't have copied those
references to change-class from the old text. Oh, wait, it wasn't
an editing spazz, I said a bit later in the message that I was just
finishing up the amendments from last March and not trying also to do
all the rewriting of the document to suit our latest mind changing.
However I agree with the new wording, except for the typo you
introduced (missing "is").
On the issue of whether we say "class slot" or "shared slot", I do not
have an opinion. It would be nice if we could work out the wording of
this part of the document without doing a lot of switching back and
forth on that terminology, though; we could fix the terminology
afterwards.
This is fine so far. But the following is problematic.
At the moment a class is redefined, if the new version of the
class contains a shared slot of the same name as any shared slot in
the old version of the class, the value of that slot will be the
same in both.
Should this be true? Will changing the context of the defclass form not
effect the value of the class slot. I think this is a mistake.
Redefining the class should set the value of the class slots, and
whether that value is EQL or not must depend on the evaluation form and
context.
I haven't been able to figure out what you mean here. Editing out the
parts of your comment I don't understand leaves "Redefining the class
should set the value of the class slots", which we've never said before
and I don't think I agree with. Here are two cases to think about:
(1) A class slot whose value is a list of all the instances, initialized
to nil when the class is first defined and updated by an
initialize-instance method.
(2) A class slot whose value is the price of an instance, initialized by
:initform in the defclass.
In case 1, you surely don't want the slot value reset to nil when you
redefine the class. In case 2, you might want to set the price to the
new value of the :initform. If redefining a class always reinitializes
class slots, you can't do case 1. If it never reinitializes class slots,
you can work around case 2 by doing setf of slot-value at the same
time as you redefine the class.
I also have a problem with:
If in the new version of the class there is a shared slot of
the same name as any local slot in the old version of the class,
that shared slot is initialized to the value of the corresponding
{\bf :initform} option of the new class, or remains uninitialized
if the new version of the class does not specify or inherit the
{\bf :initform} option for that slot. Shared slots are not
affected by the updating of an instance.
This again seems mistaken for me. What value should go in the new
shared slot -- that is, from which particular instance will it be set.
You didn't read what I said, which is that the new shared slot is
initialized from the initform, not from any particular instance. That
indicates that what I wrote wasn't written clearly enough.
I think the correct paragraph would read:
If in the new version of the class there is a class slot of the
same name as any instance slot in the old version of the class,
that class slot is initialized by the redefinition of the class,
and is not affeced by the value of any slot in any of the
instances.
The last two lines are the addition here, and it seems like a good idea
to bring this out very explicitly. I don't know that it was necessary
to remove the definition of what it means for a slot to be initialized
by the redefinition of the class.
If there is an instance slot in the new definition of
the class that is the same name as a class slot in the old version
of the class, then on updating, the value of each instance slot is
given the same (EQL) value as the that in the old class slot. If
the class slot in the old version of the class was uninitialized,
then the instance slots in the new instances are initialized as if
they were new slots in the instance.
This was already covered by the first paragraph, which evidently needs
to be made more explicit that when it says "the same name as any slot"
it means any slot, including both class and instance slots. However,
I don't agree with your last sentence. I think it's much simpler to say
that uninitialized slots remain uninitialized, regardless of the allocation,
rather than to make a special case for slots that are both uninitialized
and switching from class allocation to instance allocation.
Maybe a more succinct way to say this is that if you really want to
reinitialize a slot, you should remove it and then add it back.
Actually, though, now that we got rid of the sequential class
redefinition idea, that doesn't work unless you contrive to update
every instance before redefining the class the second time. I
shouldn't be surprised that one has to give up a few things when
adopting the simpler scheme.
Looks like we need a couple more iterations on the writing of this
couple of paragraphs.
∂28-Sep-87 1549 kempf%hplabsz@hplabs.HP.COM Re: draft of built-in method combination types
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:49:01 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 15:48:45 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 28 Sep 87 16:49:43 pdt
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: draft of built-in method combination types
X-Mailer: mh6.5
In-Reply-To: Your message of Mon, 28 Sep 87 11:14:24 -0500.
<2768832864-16341119@Jenner>
Date: Mon, 28 Sep 87 16:49:41 MST
Message-Id: <21568.559867781@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
>
> A primary method has the name of the method combination type as its
> sole qualifier. For example, the method combination type AND
> recognizes methods whose sole qualifier is AND; these are primary
> methods.
> I thougt about it some more and found two disadvantages in qualifying
> primary methods:
> When one wants to change the method-combination type (from NCONC to
> APPEND), one has to change the qualifiers of all the primary methods in
> the source files.
> Automatic method generators will have to know about the method
> combination type.
>
Another disadvantage is forbidding CALL-NEXT-METHOD within primaries, which
was in my earlier message. This introduces an additional level of
conceptual complexity which destroys the clean semantics of
CALL-NEXT-METHOD.
jak
∂28-Sep-87 1556 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: fixing our problems with setf
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:56:13 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243560; Mon 28-Sep-87 18:57:01 EDT
Date: Mon, 28 Sep 87 18:57 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: fixing our problems with setf
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870928-141913-19460@Xerox>
Message-ID: <870928185703.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Sep 87 14:18 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
As with regular functions, associated with any given name you
can have a setf function or a setf macro, but not both. This means
that one does not define a setf function (with defmethod or
defgeneric) and also call defsetf. The mere act of defining the
setf function is enough to tell setf what to do.
Does this mean that if I do a
(defsetf foo ...)
(defun (setf foo) ...)
then the setf macro has been undone. (I hope so).
And similarly in the other direction.
That's the idea. I didn't give a reference to CLtL because, earlier,
I wasn't able to find anything that says what
(defmacro foo ...)
(defun foo ...)
does (nor what the other direction does). I guess this is supposed to
be covered by the second to last sentence on p.67 and the second to last
sentence on p.144, although neither is as clear as I would like.
I changed my file copy of this message to say
Note that defining a setf function after doing a
defsetf or a define-setf-method removes the setf macro, and conversely
defining a setf macro undefines the setf function.
∂28-Sep-87 1612 kempf%hplabsz@hplabs.HP.COM Re: Various Topics Discussed Last Week
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:11:49 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 16:10:56 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 28 Sep 87 17:11:52 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Various Topics Discussed Last Week
X-Mailer: mh6.5
In-Reply-To: Your message of Mon, 28 Sep 87 13:07:00 -0400.
<870928130706.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 28 Sep 87 17:11:49 MST
Message-Id: <21934.559869109@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> One way out of this dilemma is to simply have the :BEFORE method and the
> :AROUND method for INITIALIZE-INSTANCE be reserved for the system.
> Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE.
> This would leave no places where user defined hooks could be inserted before the
> INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods
> at their own peril, as is the case with redefining any system defined
> method (or function for that matter).
> I don't see how the methods could be reserved, since there isn't just one;
> there's one for every class. However, your proposal is essntially the same
> as my proposal to have a specialized kind of method combination for these
> generic functions, so that user-defined methods would naturally go only where
> they made sense. For some reason that proposal provoked a lot of opposition,
> so I dropped it. It could be revived if there is renewed interest. In the
> meantime, I won't try to put anything about this into the draft object
> creation proposal.
They are reserved in the same way that the symbol INITIALIZE-INSTANCE
is reserved for a particular generic function which has system defined
methods that you redefine at your own risk. I think what I meant is
that the qualified methods are defined by the system for use in
implementation dependent ways, in the same way a default
INITIALIZE-INSTANCE method is provided. I don't think that
INITIALIZE-INSTANCE needs to be signalled out with a special kind of
method combination.
However, if there's strong opposition to this, then maybe an addition to the
paragraph in the initialization concepts section which begins "Note:
nothing is guaranteed about ...." along the lines of "Users are encouraged
to redefine the INITIALIZE-INSTANCE primary if they want to modify slot
initialization, rather than using a :BEFORE qualifed method, since the default
INITIALIZE-INSTANCE method will always modify the slots if required by
the -initarg-list-, regardless of the initial state of the slots." This would
at least warn users that :BEFORE method combination won't work as they may
think in this case.
jak
∂28-Sep-87 1648 Bobrow.pa@Xerox.COM Re: Various Topics Discussed Last Week
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:48:27 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 28 SEP 87 16:41:45 PDT
Date: 28 Sep 87 16:41 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Various Topics Discussed Last Week
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870928-164145-1052@Xerox>
[Should the name of this option be :DEFAULT-INITARGS or
:DEFAULT-INITARG ?]
:DEFAULT-INITARGS to emphasize that it is a list, each of which itself
is a DEFAULT-INITARG.
JAK Something needs to be said here about the case where
a user writes a :BEFORE method and SETF's the slot there. From
the rest of the text, it sounds as if INITIALIZE-INSTANCE is
permitted to clobber that slot.
Moon: I think that's what we agreed to at the meeting a couple weeks
ago.
JAK This makes :BEFORE methods on INITIALIZE-INSTANCE less then
useful
for slot initialization. The result requires either that
INITIALIZE-INSTANCE be singled out in a particular way to
prohibit
:BEFORE methods, or allows the system to arbitrarily clobber
something
the programmer has done.
Moon: I agree with you.
First, the clobbering is not arbitrary, but a well defined part of the
interface. Second, It is easy for a :BEFORE method to get around this
by simply side-effecting the initarg list, as well as by doing its setf.
Programmers using method combination always have to take into account
the contract of methods they are combined with, or possibly lose. I
don't see this as any worse than:
JAK Users redefine these qualified methods
at their own peril, as is the case with redefining any system
defined
method (or function for that matter).
I guess the upshot is that I am not uphappy for users using :BEFORE
methods, since they can achieve the results they want easily, and can
know the effect of their programs.
∂28-Sep-87 1651 Bobrow.pa@Xerox.COM Re: Various Topics Discussed Last Week
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:51:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 16:51:05 PDT
Date: 28 Sep 87 16:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Various Topics Discussed Last Week
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 28 Sep 87 13:07 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870928-165105-1096@Xerox>
JAK: Someone could write a forwarding metaobject method as:
(defmethod no-applicable-method
((gf forwarding-generic-function)
&rest all-arguments)
(apply #'forward-method all-arguments))
A user can do something similar with the default method,
with somewhat hairier code.
Moon:The problem with this is that people want forwarding for "all"
generic functions, not just specially identified ones. I put "all"
in quotation marks because after they have thought about it deeply
they usually discover that there are some generic functions that
mustn't forward.
However, I like your suggestion anyway. If we make the
arguments to no-applicable-method be generic-function &rest
all-arguments, someone who wants to do delegation can redefine the
default method to call a new generic function with whatever
arguments they want. Not having that built into CLOS doesn't make
it impossible to add on one's own.
Much as I dislike having to give up this feature, I have to admit that
what is being given up is one generic function call after redefining the
default method. Given the groans I heard when I apecialized on the
first argument, I will write this up as suggested, with only two
arguments to no-applicable-method, generic-function and
function-arguments.
danny
∂28-Sep-87 1734 kempf%hplabsz@hplabs.HP.COM Re: fixing our problems with setf
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 17:34:02 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 17:14:58 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 28 Sep 87 18:15:55 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: fixing our problems with setf
X-Mailer: mh6.5
In-Reply-To: Your message of Mon, 28 Sep 87 16:55:00 -0400.
<870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 28 Sep 87 18:15:52 MST
Message-Id: <22711.559872952@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Add to Common Lisp the same concept of "setf functions" that we are
> already introducing in CLOS. Right now, Common Lisp only has "setf
I endorse this. I don't see any need to change the TRACE proposal,
since (SETF <function name>) was one of the function specifications
included. Do you?
jak
∂28-Sep-87 1800 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Topics Discussed Last Week
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 18:00:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243663; Mon 28-Sep-87 21:01:23 EDT
Date: Mon, 28 Sep 87 21:01 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Various Topics Discussed Last Week
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870928-164145-1052@Xerox>
Message-ID: <870928210120.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Sep 87 16:41 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
JAK This makes :BEFORE methods on INITIALIZE-INSTANCE less then
useful
It is easy for a :BEFORE method to get around this
by simply side-effecting the initarg list
I don't think we have said that this is either possible or legal.
In fact since the initarg list is received by the :BEFORE method
for INITIALIZE-INSTANCE as an &rest arg list (if received at all;
the method might have only &key parameters and no &rest parameter),
I believe it would be a violation of Common Lisp to modify it.
Once upon a time we allowed side-effecting the initarg list in
Flavors, so I have reasons to be opposed to allowing it in CLOS.
Programmers using method combination always have to take into account
the contract of methods they are combined with, or possibly lose.
I agree that that is true.
I don't see this as any worse than:
JAK Users redefine these qualified methods
at their own peril, as is the case with redefining any system
defined method (or function for that matter).
I guess the upshot is that I am not uphappy for users using :BEFORE
methods, since they can achieve the results they want easily, and can
know the effect of their programs.
I still think that by allowing :BEFORE methods on INITIALIZE-INSTANCE we
are creating an attractive nuisance. Perhaps the good effects of using
standard method combination instead of introducing something special
outweigh the bad effects of occasionally trapping a user into trying to
write code that won't work, but it's something to think about.
∂28-Sep-87 1804 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: fixing our problems with setf
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 18:04:27 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243671; Mon 28-Sep-87 21:04:59 EDT
Date: Mon, 28 Sep 87 21:05 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: fixing our problems with setf
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <22711.559872952@hplabsz>
Message-ID: <870928210505.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 28 Sep 87 18:15:52 MST
From: kempf%hplabsz@hplabs.HP.COM
> Add to Common Lisp the same concept of "setf functions" that we are
> already introducing in CLOS. Right now, Common Lisp only has "setf
I endorse this. I don't see any need to change the TRACE proposal,
since (SETF <function name>) was one of the function specifications
included. Do you?
No, the TRACE proposal should fit right in. When I said TRACE needed
to be changed, I was referring to the current state of Common Lisp, before
implementation of any proposals.
∂28-Sep-87 1836 RPG Shared/local;class/instance
To: common-lisp-object-system@SAIL.STANFORD.EDU
Danny writes:
``I can't imagine them knowing anything else after they read the
documentation once.''
Names can cloud an explanation: If I named the FFT function
DELETE-ALL-FILES, one might allow the possibility of a user believing
something else after reading the documentation (even after reading it a
hundred times). Here :class is not such an offender, but the only reliable
impression from the name and explanation is that the slot is in the class
object - perhaps the class uses it for private information and the instances
cannot see it: that information would be conveyed by :shared.
Danny again:
``I answered your last question earlier -- referring to the use of dynamic
as an implementation tradeoff that is not relevant for shared slots.''
But the irrelevancy is not necessary.
Danny adds:
I don't think we need yet another programming language.... I would rather
use the symbol that specifies the option as our means of referring to the
type of slot, rather than another word that refers to a property of that
kind of slot.''
I suppose it's open for debate whether its type is a property of a thing,
but I agree that another programming language is bad idea.
Therefore, I simply believe that :shared is a better name than :class
in terms of being intuitive.
-rpg-
∂28-Sep-87 1918 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Redefining Classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 19:18:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243701; Mon 28-Sep-87 22:18:15 EDT
Date: Mon, 28 Sep 87 22:18 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Redefining Classes
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870928-145131-19538@Xerox>
Message-ID: <870928221802.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Summary: When redefining a class causes instances to be updated can be
implementation-dependent. (update-from-obsolete-instance instance
added-slot-names removed-slot-names removed-bound-slot-values); the
primary method uses initforms to initialize the slots whose names are
listed in added-slot-names. update-from-obsolete-instance is called no
later than the first slot read or write after the class is redefined.
The retained slot values are already in place when
update-from-obsolete-instance is called. Those are my opinions.
Date: 28 Sep 87 14:51 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
If the redefinition of a class causes the structure of
its instances to be different...
I think we're going to have to define this more precisely. I
see two options:
(1) Adding or removing an instance slot definitely changes the
structure, and some other operations may also change the structure,
depending on the implementation.
(2) The structure changes if and only if the value of
(class-all-instance-slot-names class) is not EQUAL to its previous
value. I made up the function name class-all-instance-slot-names,
but you get the idea. Note how class-all-slot-names won't work.
The big difference between option 1 and option 2 is that with
option 2, a given sequence of defclass forms will produce exactly
the same sequence of calls to make-instances-obsolete in all
implementations.
I'm inclined to option 2, because it is more precise, but I'm
worried that this might rule out some implementation possibility.
Also, for this to be meaningful and portable, we have to define the
exact order of slots produced by slot inheritance, which is not
something we've had to specify before now.
I agree with you on the choice of how one specifies this. In the
metaobject protocol, we currently have a generic function
all-slot-names class &optional allocation
which returns a list of slot names.
The allocation argument can be an allocation symbol (e.g. :instance,
:class), or nil meaning names for slots regardless of allocation. For
allocation = :instance, the list returned by the implementation should
be one that is ordered by the implementation. Thee is no method to
specify the order of instance slots in the instance. An implementation
is free to decide on the layout (e.g. so that reversing two slot names
in a defclass form does not necessarily obsolete the instances). By
documenting all-slot-names, we can avoid the specification of the
ordering rules, and still provide a specification of what we mean.
So what you're saying is that alternatives 1 and 2 are really the same.
We can say that defclass calls make-instances-obsolete precisely when
the value of (class-all-slot-names class ':instance) is not EQUAL to its
former value, but then we can obscure that by not specifying precisely
what class-all-slot-names does. OK, let's not try to define precisely
when defclass calls make-instances-obsolete.
I have two problems with [update-obsolete-instance].
The easy problem is that I
don't like the name update-obsolete-instance, because the instance
doesn't really seem obsolete to me. One idea is to take an analogy
to class-changed and call it class-redefined. In Flavors we call
it transform-instance, but it doesn't have quite the same
semantics. It's likely that someone can think of a better name
than any of these.
We could call it update-from-obsolete-instance, or
conform-instance-to-class. Since it takes ans instance as an argument,
I don't like names like class-redefined -- which seems to focus on the
class.
Good point. update-from-obsolete-instance appeals to me, although it
might be thought to imply that two instances are involved.
Much more important, I can't implement the specification that
the slots are initially uninitialized and then they are filled in
from values saved in a property list. There are two problems, one
obvious and one subtle. The obvious problem involves slots that
were unbound originally; since there is no Lisp value that means
"unbound", there is nothing that can be put into the property list
for these slots. But if we don't put any entry in the property
list, then the desired feature that the method can tell which slots
were added or removed is lost; these slots look like they were
added, even though they weren't.
We could designate such a value (make it be the value of a globally
accessible variable). Then putting such a value in a slot would be
equivalent to making it unbound. I can hear the ARGHHH from here, but
it does make accessible something that we are having to make
programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste
(and I could be convinced on this fairly easily), why is it you could
not implement this -- is there a particular tradeoff that you are not
being explicit about?
It doesn't work to have a magic Lisp object that means "unbound" when it's
the value of a slot, because then you can never talk about that value in
any way that involves putting it into a slot. If you think that's a matter
of taste, the other answer is that my hardware has the unbound slot value
built into it, and it would cost me a couple million dollars to change it.
Here we have both the rarified philosophical argument and the businesslike
pragmatic argument.
Also, the default method you
mention below will put the :initform value into these previously
unbound slots, which seems wrong. "Unbound" should not be
confounded with "nonexistent."
I feel that making unbound slots be initialized is a feature, not a bug.
One good reason to make a class obsolete may be to cause formerly
unbound slots to be initialized. That is, one could redefine a class,
adding an initform option, and be sure that any instances that had that
slot unbound would now have it bound to the specified value.
To my way of thinking it is philosophically inconsistent to have different
rules for whether a slot's value is changed when the class is redefined,
depending on slot-boundp. At this level, "unbound" should be treated like
just another value. I hope you don't think this is too inconsistent with
what I said just above: "unbound" is a slot value, but it is not a Lisp
object.
I think it's better to do things like filling in previously unbound
slots in old instances with update-from-obsolete-instance (or whatever
name we choose) methods.
The subtle problem involves some language extensions that we
have, allowing slots to have contents that cannot be expressed as
Lisp values in a property list. For instance, there is a mechanism
similar to Prolog logic-variables which allows two slots to be
linked together. This linkage has to be preserved in the face of
class redefinition.
Can such linked values only be used inside of objects, and not within
lists? I though inivisible pointers can be used anywhere. I don't
understand what the assumptions underlying this extension are.
They can be used in lists, but the point is that care needs to be exercised
when moving them around. The net effect is that the code that moves slot
values from one piece of memory to another, when an instance has to have
new memory allocated for it, can't be written portably in our system. But I
don't see why anyone would want a portable version of it.
For these reasons, I believe it is better to specify that the
slot values are conveyed from the old structure of the instance to
the new structure by the low-level implementation, not by a
user-replaceable method. Thus when the generic function
update-obsolete-instance is called, all slots that existed in the
old class definition, and existed as instance slots in the new
class definition, already have their values, as the same low-level
bits. I can't see any need for even a meta-user to replace this
with something else.
Without the reasons given above, I still like this proposal as well as
the one I wrote up. It supports the proposed model at a better level.
I suggest conveying the desired information directly, rather
than trying to be clever: Give update-obsolete-instance four
arguments:
the instance
a list of the names of all added slots
a list of the names of all deleted slots
a property list giving the values of all deleted, bound slots
I actually think this is fine. But I would also say that the underlying
implemention also initializes existing slots that were unbound, using
the initforms in the class, if any.
I still think that is philosophically inconsistent.
I would say the default method initializes only the
newly added slots.
Fine I will write it up this way.
Thanks.
Because update-obsolete-instance is user code, its
operation can be seen by the user; but the model that CLOS
supports is that as far as the user can tell, all the existing
instances of a class are updated as soon as the class
redefinition happens. This implies that the user must define a
method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing
instances (for example, to method call or slot access time),
but users should never be able to see the untransformed
instance.
We're going to have to specify this a little more precisely, I
suspect. We should specify when is the latest time that an
implementation can call update-obsolete-instance, and then say that
it is permitted to call it any time earlier (after the class has
been redefined). I now believe that the latest time can simply be
the time any of the four slot access and modification functions (or
internal equivalent) is called, in spite of all the flaming against
this we engaged in while discussing Danny's proposal at the meeting
last week.
Agreed.
I'd like to hear Patrick's opinion on this timing issue before I have much
confidence that we have figured it out.
∂29-Sep-87 0859 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 08:59:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 08:59:34 PDT
Date: 29 Sep 87 08:59 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Amendments requiring additional writing
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 28 Sep 87 18:43 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870929-085934-1876@Xerox>
I haven't been able to figure out what you mean here. Editing
out the parts of your comment I don't understand leaves "Redefining
the class should set the value of the class slots", which we've
never said before and I don't think I agree with. Here are two
cases to think about:
(1) A class slot whose value is a list of all the instances,
initialized to nil when the class is first defined and updated by
an initialize-instance method.
(2) A class slot whose value is the price of an instance,
initialized by :initform in the defclass.
In case 1, you surely don't want the slot value reset to nil
when you redefine the class. In case 2, you might want to set the
price to the new value of the :initform. If redefining a class
always reinitializes class slots, you can't do case 1. If it never
reinitializes class slots, you can work around case 2 by doing setf
of slot-value at the same time as you redefine the class.
These are interesting examples, and cause one to ponder.
I think the difference here is like the difference between
editing a function definition on a file and
editing the actual function list structure with a structure editor.
Changing a function using a structure editor affects existing calls, and
editing the file cannot. I think the corresponding cases for classes
are:
use the metaobject protocol to update an existing class using the slot
objects that currently exist,
and reevaluating the defclass form.
In the latter case, the specification only guarantees that class
objectsame object identity is preserved, unless we want to go more into
a DWIM mode, that is guess which items in the new definition are meant
to yield the same result as the old case.
If in the new version of the class there is a shared slot of
the same name as any local slot in the old version of the class,
that shared slot is initialized to the value of the corresponding
{\bf :initform} option of the new class, or remains uninitialized
if the new version of the class does not specify or inherit the
{\bf :initform} option for that slot. Shared slots are not
affected by the updating of an instance.
This again seems mistaken for me. What value should go
in the new shared slot -- that is, from which particular
instance will it be set.
You didn't read what I said, which is that the new shared slot
is initialized from the initform, not from any particular instance.
That indicates that what I wrote wasn't written clearly enough.
You are right. I didn't read well enough. Your text is correct.
danny
∂29-Sep-87 0928 RPG Various Decisions
To: Common-lisp-object-system@SAIL.STANFORD.EDU
On the implicit block proposal, I agree with Moon's writeup.
On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential
confusion that RPLACD might cause for users.
-rpg-
∂29-Sep-87 0945 Gregor.pa@Xerox.COM Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 09:45:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 09:45:38 PDT
Date: 29 Sep 87 09:45 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Issues on Dynamic Extent for CALL-NEXT-METHOD
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 21 Sep 87
21:35 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870929-094538-1995@Xerox>
Today I talked to Guy Steele on the phone, and I told him about
generic functions, methods, and call-next-method without expressing
any opinions about them. When I asked what extent call-next-method
should have, he thought for a while and stated `dynamic.' When I
asked why, he gave argument 4, which talks about the capture of
hidden state.
I guess I don't think this has any weight because I have no way of
knowing exactly how you described this to him. Many of your messages
suggest that you think of a generic function as a 'black box' with
hidden state, its likely you conveyed that feeling while you were
describing it.
I believe this is a bad way to think of them, I don't see any hidden
state in a generic function at all. In particular, we worked very hard
while we were doing declarative method combination to make sure that
there was no hidden state; that the entire behavior of the method
combination was exposed and clear.
I really think it would be unfortunate to make this dynamic extent. It
will just be yet another piece of inconvenience and complication we
inflict on people trying to understand Common Lisp. Whats more, once
people really get to understand generic functions and method
combinations they will scratch their heads and wonder why the hell we
did it.
∂29-Sep-87 1124 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:24:18 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 11:24:13 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 29 Sep 87 12:25:11 pdt
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Various Decisions
X-Mailer: mh6.5
In-Reply-To: Your message of 29 Sep 87 09:28:00 -0700.
Date: Tue, 29 Sep 87 12:25:07 MST
Message-Id: <1122.559938307@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential
> confusion that RPLACD might cause for users.
I still think it would be better to just let this be handled by
the error system, but NEXT-METHOD is better than NEXT-METHODS.
∂29-Sep-87 1150 Bobrow.pa@Xerox.COM Re: Shared/local;class/instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:49:57 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 10:29:40 PDT
Date: 29 Sep 87 10:29 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Shared/local;class/instance
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 28 Sep 87
18:36 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870929-102940-2073@Xerox>
Therefore, I simply believe that :shared is a better name than
:class in terms of being intuitive.
The issue is what the pair of names should be; instance/class or
local/shared. I have argued on the basis of possible extensions that
we should use :instance and :class. Another argument is that instance
and class are used in Smalltalk with the same meanings. Hence people
who take a course in object oriented programming using Smalltalk will
not have to learn yet another isomorphic terminology.
∂29-Sep-87 1150 Bobrow.pa@Xerox.COM Re: Various Decisions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:50:16 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 10:40:35 PDT
Date: 29 Sep 87 10:40 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Various Decisions
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 29 Sep 87
09:28 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870929-104035-2118@Xerox>
On the implicit block proposal, I agree with Moon's writeup.
Fine with me.
On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential
confusion that RPLACD might cause for users.
I don't care. Remember that NEXT-METHODS was introduced first as an
improvement over call-next-method-or-nil. Hence its primary purpose was
to allow a programmer to avoid using call-next-method when it would
signal an error. NEXT-METHOD satisfies that goal. Question: Is there
anything else we want to make available at run time? If we are only
getting the next method, perhaps we ought to only have
NEXT-METHOD-P
which returns T or NIL; this might allow some optimizations of the
combined code.
∂29-Sep-87 1222 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Decisions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 12:22:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244218; Tue 29-Sep-87 15:23:13 EDT
Date: Tue, 29 Sep 87 15:23 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Various Decisions
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870929-104035-2118@Xerox>
Message-ID: <870929152320.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Sep 87 10:40 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential
confusion that RPLACD might cause for users.
I don't care. Remember that NEXT-METHODS was introduced first as an
improvement over call-next-method-or-nil. Hence its primary purpose was
to allow a programmer to avoid using call-next-method when it would
signal an error. NEXT-METHOD satisfies that goal. Question: Is there
anything else we want to make available at run time? If we are only
getting the next method, perhaps we ought to only have
NEXT-METHOD-P
which returns T or NIL; this might allow some optimizations of the
combined code.
Okay, here's what I have written down about this topic now:
The function NEXT-METHODS was added in September. It is scoped the same as
CALL-NEXT-METHOD, takes no arguments, and returns a list of method objects,
of which the first is the one that CALL-NEXT-METHOD calls. The effect of
modifying the list is undefined.
Moon and Gabriel like NEXT-METHOD better; it returns a method object or NIL.
Kempf likes NEXT-METHOD better than NEXT-METHODS, but likes nothing even
better, since CALL-NEXT-METHOD could signal a condition.
Bobrow: NEXT-METHOD-P, returning no unnecessary information, is even better.
Moon: I like that.
∂29-Sep-87 1300 kempf%hplabsz@hplabs.HP.COM Re: Shared/local;class/instance
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 12:59:54 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 12:59:06 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 29 Sep 87 14:00:02 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Shared/local;class/instance
X-Mailer: mh6.5
In-Reply-To: Your message of 29 Sep 87 10:29:00 -0700.
<870929-102940-2073@Xerox>
Date: Tue, 29 Sep 87 13:59:58 MST
Message-Id: <2048.559943998@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Therefore, I simply believe that :shared is a better name than
> :class in terms of being intuitive.
> The issue is what the pair of names should be; instance/class or
> local/shared. I have argued on the basis of possible extensions that
> we should use :instance and :class. Another argument is that instance
> and class are used in Smalltalk with the same me> anings. Hence people
> who take a course in object oriented programming using Smalltalk will
> not have to learn yet another isomorphic terminology.
Danny has made a good point. Compatibility with Smalltalk will make
skill transferance easier.
∂29-Sep-87 1415 Pavel.pa@Xerox.COM Re: Various Decisions
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:15:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 12:06:01 PDT
Date: Tue, 29 Sep 87 12:05:58 PDT
From: Pavel.pa@Xerox.COM
Subject: Re: Various Decisions
In-reply-to: <870929-104035-2118@Xerox>
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870929-120601-2316@Xerox>
Why are folks so opposed to using the error system instead of this
NEXT-METHOD function? It seems the obvious thing, leading to more
readable code with a clearer intent.
Pavel
∂29-Sep-87 1440 kempf%hplabsz@hplabs.HP.COM Re: Status of CLOS decisions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:40:38 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 14:37:35 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 29 Sep 87 15:38:33 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Status of CLOS decisions
X-Mailer: mh6.5
In-Reply-To: Your message of Tue, 22 Sep 87 23:07:00 -0400.
<870922230752.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 29 Sep 87 15:38:31 MST
Message-Id: <3388.559949911@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> REVISED ``INHERITANCE OF SLOTS AND SLOT OPTIONS'' SECTION:
This looks good to me, with the proviso that "shared slot" be replaced
by whatever terminology we decide on. After reading through it,
I can't find any ambiguity in the wording. The reference to :DYNAMIC
slots needs to be removed, however. It seems to be more concise than
the current description.
∂29-Sep-87 1444 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Various Decisions
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:43:53 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244370; Tue 29-Sep-87 17:35:57 EDT
Date: Tue, 29 Sep 87 17:36 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Various Decisions
To: Pavel.pa@Xerox.COM
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870929-120601-2316@Xerox>
Message-ID: <870929173603.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Tue, 29 Sep 87 12:05:58 PDT
From: Pavel.pa@Xerox.COM
Why are folks so opposed to using the error system instead of this
NEXT-METHOD function? It seems the obvious thing, leading to more
readable code with a clearer intent.
Note that condition handlers have dynamic rather than lexical "scope"
(or whatever word you want to use for the portion of program that they
affect). Thus a HANDLER-CASE around a CALL-NEXT-METHOD might actually
intercept some inner CALL-NEXT-METHOD in some inner, nested method.
There's no way to turn off the handler as soon as the CALL-NEXT-METHOD
has succeeded in passing control to the next method.
∂29-Sep-87 1514 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 15:13:42 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 15:10:55 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 29 Sep 87 16:11:52 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: Pavel.pa@Xerox.COM, Common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Various Decisions
X-Mailer: mh6.5
In-Reply-To: Your message of Tue, 29 Sep 87 17:36:00 -0400.
<870929173603.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 29 Sep 87 16:11:46 MST
Message-Id: <3966.559951906@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Date: Tue, 29 Sep 87 12:05:58 PDT
> From: Pavel.pa@Xerox.COM
> Why are folks so opposed to using the error system instead of this
> NEXT-METHOD function? It seems the obvious thing, leading to more
> readable code with a clearer intent.
> Note that condition h> andlers have dynamic rather than lexical "scope"
> (or whatever word you want to use for the portion of program that they
> affect). Thus a HANDLER-CASE around a CALL-NEXT-METHOD might actually
> intercept some inner CALL-NEXT-METHOD in some inner, nested method.
> There's no way to turn off the handler as soon as the CALL-NEXT-METHOD
> has succeeded in passing control to the next method.
Well, my reading of the Pitman error proposal (admittedly dated 1985) is that
something like this should work:
(catch-condition no-next-method &body (call-next-method))
should work. If there is no next method, then NIL will be returned as
the first value of the form, and the condition "object" as the second.
Of course, the condition NO-NEXT-METHOD must first be defined.
∂29-Sep-87 1529 RPG Various Decisions
To: Common-lisp-object-system@SAIL.STANFORD.EDU
On condition handlers instead of NEXT-METHOD:
It seems that condition handlers are an appropriate vehicle for dealing
with exceptional conditions, or at least with conditions that are not
routinely encountered. For example, in a Lisp in which CAR and CDR of NIL
signal errors, one would be surprised to see the naive SUBST function
written like this:
(defun subst (x y z)
(cond ((eq x z) y)
(t (cons (subst x y (car z))
(subst x y (cdr z))))))
with condition handlers for the null and non-CONS cases.
Similarly, if it is the case (and I think it likely) that a programmer
frequently wants to CALL-NEXT-METHOD when there might not be one, then he
will likely want to write:
(when (next-method) (call-next-method))
or use a non-error-signaling version of CALL-NEXT-METHOD rather than
program a condition handler.
-rpg-
∂29-Sep-87 1625 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Redefining Classes
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 16:24:44 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa10877; 29 Sep 87 18:30 EDT
Received: from csl.ti.com by RELAY.CS.NET id av13799; 29 Sep 87 18:12 EDT
Received: from dsg by tilde id AA17297; Tue, 29 Sep 87 16:55:49 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Tue, 29 Sep 87 12:25:56 CDT
Message-Id: <2768923341-5262035@Jenner>
Date: Tue, 29 Sep 87 12:22:21 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Redefining Classes
In-Reply-To: Msg of Mon, 28 Sep 87 22:18 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 28 Sep 87 22:18 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Summary: When redefining a class causes instances to be updated can be
implementation-dependent. (update-from-obsolete-instance instance
added-slot-names removed-slot-names removed-bound-slot-values); the
primary method uses initforms to initialize the slots whose names are
listed in added-slot-names. update-from-obsolete-instance is called no
later than the first slot read or write after the class is redefined.
The retained slot values are already in place when
update-from-obsolete-instance is called. Those are my opinions.
I have two problems with [update-obsolete-instance].
The easy problem is that I
don't like the name update-obsolete-instance, because the instance
doesn't really seem obsolete to me. One idea is to take an analogy
to class-changed and call it class-redefined. In Flavors we call
it transform-instance, but it doesn't have quite the same
semantics. It's likely that someone can think of a better name
than any of these.
We could call it update-from-obsolete-instance, or
conform-instance-to-class. Since it takes ans instance as an argument,
I don't like names like class-redefined -- which seems to focus on the
class.
Good point. update-from-obsolete-instance appeals to me, although it
might be thought to imply that two instances are involved.
We could call it update-instance-structure. We talked about the structure
of an instance being changed in the writeup.
Much more important, I can't implement the specification that
the slots are initially uninitialized and then they are filled in
from values saved in a property list. There are two problems, one
obvious and one subtle. The obvious problem involves slots that
were unbound originally; since there is no Lisp value that means
"unbound", there is nothing that can be put into the property list
for these slots. But if we don't put any entry in the property
list, then the desired feature that the method can tell which slots
were added or removed is lost; these slots look like they were
added, even though they weren't.
We could designate such a value (make it be the value of a globally
accessible variable). Then putting such a value in a slot would be
equivalent to making it unbound. I can hear the ARGHHH from here, but
it does make accessible something that we are having to make
programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste
(and I could be convinced on this fairly easily), why is it you could
not implement this -- is there a particular tradeoff that you are not
being explicit about?
It doesn't work to have a magic Lisp object that means "unbound" when it's
the value of a slot, because then you can never talk about that value in
any way that involves putting it into a slot. If you think that's a matter
of taste, the other answer is that my hardware has the unbound slot value
built into it, and it would cost me a couple million dollars to change it.
Here we have both the rarified philosophical argument and the businesslike
pragmatic argument.
As Moon says, "unbound" is a value, but not a lisp object. I would
oppose a proposal saying that we can pass it around and storing it into
a slot. Note that SLOT-MAKUNBOUND would not implemented using CLtL
primitives, but lower level ones that don't see lisp objects but bits.
To my way of thinking it is philosophically inconsistent to have different
rules for whether a slot's value is changed when the class is redefined,
depending on slot-boundp. At this level, "unbound" should be treated like
just another value. I hope you don't think this is too inconsistent with
what I said just above: "unbound" is a slot value, but it is not a Lisp
object.
I think it's better to do things like filling in previously unbound
slots in old instances with update-from-obsolete-instance (or whatever
name we choose) methods.
I agree. If you want to reinitialize some slot, modify the method for
"update-from-obsolete-instance (or whatever name we choose)" and call
MAKE-INSTANCES-OBSOLETE.
The subtle problem involves some language extensions that we
have, allowing slots to have contents that cannot be expressed as
Lisp values in a property list. For instance, there is a mechanism
similar to Prolog logic-variables which allows two slots to be
linked together. This linkage has to be preserved in the face of
class redefinition.
Can such linked values only be used inside of objects, and not within
lists? I though inivisible pointers can be used anywhere. I don't
understand what the assumptions underlying this extension are.
They can be used in lists, but the point is that care needs to be exercised
when moving them around. The net effect is that the code that moves slot
values from one piece of memory to another, when an instance has to have
new memory allocated for it, can't be written portably in our system. But I
don't see why anyone would want a portable version of it.
I hadn't though of that. This is true, we must preserve those
structures. The problem is the same as with unbound slots, invisible
pointers are not lisp objects.
For these reasons, I believe it is better to specify that the
slot values are conveyed from the old structure of the instance to
the new structure by the low-level implementation, not by a
user-replaceable method. Thus when the generic function
update-obsolete-instance is called, all slots that existed in the
old class definition, and existed as instance slots in the new
class definition, already have their values, as the same low-level
bits. I can't see any need for even a meta-user to replace this
with something else.
Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same
reasons?
Because update-obsolete-instance is user code, its
operation can be seen by the user; but the model that CLOS
supports is that as far as the user can tell, all the existing
instances of a class are updated as soon as the class
redefinition happens. This implies that the user must define a
method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing
instances (for example, to method call or slot access time),
but users should never be able to see the untransformed
instance.
We're going to have to specify this a little more precisely, I
suspect. We should specify when is the latest time that an
implementation can call update-obsolete-instance, and then say that
it is permitted to call it any time earlier (after the class has
been redefined). I now believe that the latest time can simply be
the time any of the four slot access and modification functions (or
internal equivalent) is called, in spite of all the flaming against
this we engaged in while discussing Danny's proposal at the meeting
last week.
Agreed.
I'd like to hear Patrick's opinion on this timing issue before I have much
confidence that we have figured it out.
It's OK with me. It is important that all the metaclass primitive that
we specify have to work the same way. The meta-user should not get hold
of a value coming from a non-updated instance.
Patrick.
∂29-Sep-87 1732 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Various Topics Discussed Last Week
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:32:24 PDT
Received: from [128.89.1.80] by RELAY.CS.NET id ak10701; 29 Sep 87 18:14 EDT
Received: from csl.ti.com by RELAY.CS.NET id ai13799; 29 Sep 87 18:01 EDT
Received: from Jenner by tilde id AA15847; Tue, 29 Sep 87 16:14:20 CDT
Message-Id: <2768937138-6091027@Jenner>
Date: Tue, 29 Sep 87 16:12:18 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Various Topics Discussed Last Week
In-Reply-To: Msg of Mon, 28 Sep 87 17:05 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 28 Sep 87 17:05 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Various Topics Discussed Last Week
Date: Mon, 28 Sep 87 09:42:29 MST
From: kempf%hplabsz@hplabs.HP.COM
2) On blocks in methods:
I agree that Alternative 1 would be best. Users who want something
different can either use a :AROUND method, as Moon suggested, or
program their own generic function dispatching function, using
the metaobject protocol.
Since we all seem to be agreed on this, I added the following to my
clos-decisions file, which can be used as a resource to make sure
we don't forget to document this decision:
2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded
by an implicit block named -name-, if that is a symbol, or -name1-, if
-name- is (SETF -name1-), by analogy with DEFUN. The same applies to
methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET,
GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around
the body of a method defined by the :METHOD option to GENERIC-FUNCTION.
Dissenters speak now.
I agree with this.
7) On NEXT-METHODS:
The primary reason is for being able to tell if calling CALL-NEXT-METHOD
would signal an error. I understand Masinter's concern, and wonder if
perhaps it might not be better to handle this with Ken Pitman's error
proposal. Other than finding out whether a call to CALL-NEXT-METHOD is
valid, there isn't much use for the list of next methods, as Masinter
has pointed out.
I have no real opinion on this, but we could change this to NEXT-METHOD,
which returns the method object that CALL-NEXT-METHOD would call if
there is one, and returns NIL if CALL-NEXT-METHOD would signal the
no-more-methods error. Then we wouldn't have to worry about the
implications of consing, rplac'ing, and looking at the list.
I don't have objections to that, we could even make it a predicate,
NEXT-METHOD-P returns T if there is a next method, and NIL otherwise.
Patrick.
∂29-Sep-87 1733 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Redefining Classes
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:32:48 PDT
Received: from [128.89.1.80] by RELAY.CS.NET id ai10701; 29 Sep 87 18:14 EDT
Received: from csl.ti.com by RELAY.CS.NET id ah13799; 29 Sep 87 18:00 EDT
Received: from Jenner by tilde id AA15823; Tue, 29 Sep 87 16:13:41 CDT
Message-Id: <2768937098-6088589@Jenner>
Date: Tue, 29 Sep 87 16:11:38 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Redefining Classes
In-Reply-To: Msg of Mon, 28 Sep 87 22:18 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 28 Sep 87 22:18 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Summary: When redefining a class causes instances to be updated can be
implementation-dependent. (update-from-obsolete-instance instance
added-slot-names removed-slot-names removed-bound-slot-values); the
primary method uses initforms to initialize the slots whose names are
listed in added-slot-names. update-from-obsolete-instance is called no
later than the first slot read or write after the class is redefined.
The retained slot values are already in place when
update-from-obsolete-instance is called. Those are my opinions.
I have two problems with [update-obsolete-instance].
The easy problem is that I
don't like the name update-obsolete-instance, because the instance
doesn't really seem obsolete to me. One idea is to take an analogy
to class-changed and call it class-redefined. In Flavors we call
it transform-instance, but it doesn't have quite the same
semantics. It's likely that someone can think of a better name
than any of these.
We could call it update-from-obsolete-instance, or
conform-instance-to-class. Since it takes ans instance as an argument,
I don't like names like class-redefined -- which seems to focus on the
class.
Good point. update-from-obsolete-instance appeals to me, although it
might be thought to imply that two instances are involved.
We could call it update-instance-structure. We talked about the structure
of an instance being changed in the writeup.
Much more important, I can't implement the specification that
the slots are initially uninitialized and then they are filled in
from values saved in a property list. There are two problems, one
obvious and one subtle. The obvious problem involves slots that
were unbound originally; since there is no Lisp value that means
"unbound", there is nothing that can be put into the property list
for these slots. But if we don't put any entry in the property
list, then the desired feature that the method can tell which slots
were added or removed is lost; these slots look like they were
added, even though they weren't.
We could designate such a value (make it be the value of a globally
accessible variable). Then putting such a value in a slot would be
equivalent to making it unbound. I can hear the ARGHHH from here, but
it does make accessible something that we are having to make
programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste
(and I could be convinced on this fairly easily), why is it you could
not implement this -- is there a particular tradeoff that you are not
being explicit about?
It doesn't work to have a magic Lisp object that means "unbound" when it's
the value of a slot, because then you can never talk about that value in
any way that involves putting it into a slot. If you think that's a matter
of taste, the other answer is that my hardware has the unbound slot value
built into it, and it would cost me a couple million dollars to change it.
Here we have both the rarified philosophical argument and the businesslike
pragmatic argument.
As Moon says, "unbound" is a value, but not a lisp object. I would
oppose a proposal saying that we can pass it around and storing it into
a slot. Note that SLOT-MAKUNBOUND would not implemented using CLtL
primitives, but lower level ones that don't see lisp objects but bits.
To my way of thinking it is philosophically inconsistent to have different
rules for whether a slot's value is changed when the class is redefined,
depending on slot-boundp. At this level, "unbound" should be treated like
just another value. I hope you don't think this is too inconsistent with
what I said just above: "unbound" is a slot value, but it is not a Lisp
object.
I think it's better to do things like filling in previously unbound
slots in old instances with update-from-obsolete-instance (or whatever
name we choose) methods.
I agree. If you want to reinitialize some slot, modify the method for
"update-from-obsolete-instance (or whatever name we choose)" and call
AKE-INSTANCES-OBSOLETE.
The subtle problem involves some language extensions that we
have, allowing slots to have contents that cannot be expressed as
Lisp values in a property list. For instance, there is a mechanism
similar to Prolog logic-variables which allows two slots to be
linked together. This linkage has to be preserved in the face of
class redefinition.
Can such linked values only be used inside of objects, and not within
lists? I though inivisible pointers can be used anywhere. I don't
understand what the assumptions underlying this extension are.
They can be used in lists, but the point is that care needs to be exercised
when moving them around. The net effect is that the code that moves slot
values from one piece of memory to another, when an instance has to have
new memory allocated for it, can't be written portably in our system. But I
don't see why anyone would want a portable version of it.
I hadn't though of that. This is true, we must preserve those
structures. The problem is the same as with unbound slots, invisible
pointers are not lisp objects.
For these reasons, I believe it is better to specify that the
slot values are conveyed from the old structure of the instance to
the new structure by the low-level implementation, not by a
user-replaceable method. Thus when the generic function
update-obsolete-instance is called, all slots that existed in the
old class definition, and existed as instance slots in the new
class definition, already have their values, as the same low-level
bits. I can't see any need for even a meta-user to replace this
with something else.
Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same
reasons?
Because update-obsolete-instance is user code, its
operation can be seen by the user; but the model that CLOS
supports is that as far as the user can tell, all the existing
instances of a class are updated as soon as the class
redefinition happens. This implies that the user must define a
method for update-obsolete-instance before redefining a class.
Implementations are free to delay the conversion of existing
instances (for example, to method call or slot access time),
but users should never be able to see the untransformed
instance.
We're going to have to specify this a little more precisely, I
suspect. We should specify when is the latest time that an
implementation can call update-obsolete-instance, and then say that
it is permitted to call it any time earlier (after the class has
been redefined). I now believe that the latest time can simply be
the time any of the four slot access and modification functions (or
internal equivalent) is called, in spite of all the flaming against
this we engaged in while discussing Danny's proposal at the meeting
last week.
Agreed.
I'd like to hear Patrick's opinion on this timing issue before I have much
confidence that we have figured it out.
It's OK with me. It is important that all the metaclass primitive that
we specify have to work the same way. The meta-user should not get hold
of a value coming from a non-updated instance.
Patrick.
∂29-Sep-87 1733 DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET Re: Exact type
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:33:18 PDT
Received: from [128.89.1.80] by RELAY.CS.NET id al10701; 29 Sep 87 18:15 EDT
Received: from csl.ti.com by RELAY.CS.NET id aj13799; 29 Sep 87 18:02 EDT
Received: from Jenner by tilde id AA15864; Tue, 29 Sep 87 16:14:49 CDT
Message-Id: <2768937166-6092662@Jenner>
Date: Tue, 29 Sep 87 16:12:46 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Exact type
In-Reply-To: Msg of Mon, 28 Sep 87 13:54:27 MST from kempf%hplabsz@hplabs.hp.com
Date: Mon, 28 Sep 87 13:54:27 MST
From: kempf%hplabsz@hplabs.hp.com
Subject: Re: Exact type
>But allowing the other COMMON subtypes would makes programs non portable:
>The list of subtypes of a type is implementation dependent. We say (page
>1-14) that individual implementation can add additional subclass
>relationships as long as they don't violate CLtL.
But the subtype relationships in CLtL must still hold. Thus, any
importabilities will be the result of importabilites in the Common
Lisp type system, not in the CLOS addition. Reading the rules on
pg. 33-35, it's difficult to discern importabilities, but, talking
to Gregor (who has some experience in this area), they do exist.
However, I think the place to address the problem is to tighten up
the Common Lisp type system, not restrict EXACT-TYPE.
I don't think it's a problem with the CLtL type system. Implementations
can always specialize a built-in type without breaking the portability
of program relying on TYPEP and SUBTYPEP. However it can break the
portability of code relying on EXACT-TYPE. The user shouldn't expect
that an argument will be exactly of this built-in type. On some
machines, you cannot expect an cons cell argument to be always of the
exact type CONS.
While I don't particularly agree with this policy, I think that it gives
implementations so much latitude already that restricting EXACT-TYPE would
be inappropriate.
My way of restricting EXACT-TYPE would prevent the user from expecting
things he cannot always get.
I still think EXACT-TYPE makes sense for user defined type though.
Patrick.
∂29-Sep-87 1820 Bobrow.pa@Xerox.COM Re: Redefining Classes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 18:20:06 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 29 SEP 87 18:08:32 PDT
Date: 29 Sep 87 18:08 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Redefining Classes
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870929-180832-1165@Xerox>
After reading Patrick's message, and some more thought, I now agree with
Moon's paragraph. I am even willing to believe that common slots
(retained slots) maintain their bit contents (unbound slots are not
initialized by the updating). I have rewritten Moon's paragraph using
Patrick's suggested name change:
When redefining a class causes instances to be updated can be
implementation-dependent. The user extendible generic function
(update-instance-structure instance added-slot-names
removed-slot-names removed-bound-slot-values)
is called to complete updating of the instance structure; its
primary method uses initforms to initialize the slots whose names
are
listed in added-slot-names. update-instance-structure is called no
later than the first slot read or write of that instance after the
class is redefined. The retained slot values are already in place
when
update-instance-structure is called.
There is still the open problem of (re)initialization of class variables
on redefinition. More thoughts???
Patrick asked:
Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for
the same reasons?
I believe that update-instance-structure and class-changed should be
comparable. I will send out a revised writeup. I agree with the
general principle reiterated by Patrick, and strengthened here:
No user should ever get hold of a value coming from a
non-updated instance.
∂29-Sep-87 1931 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Exact type
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:31:26 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab11869; 29 Sep 87 20:11 EDT
Received: from csl.ti.com by RELAY.CS.NET id aa14445; 29 Sep 87 19:57 EDT
Received: from dsg by tilde id AA17433; Tue, 29 Sep 87 17:01:54 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Tue, 29 Sep 87 13:48:36 CDT
Message-Id: <2768928327-5561620@Jenner>
Date: Tue, 29 Sep 87 13:45:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Exact type
In-Reply-To: Msg of Mon, 28 Sep 87 13:54:27 MST from kempf%hplabsz@hplabs.hp.com
Date: Mon, 28 Sep 87 13:54:27 MST
From: kempf%hplabsz@hplabs.hp.com
Subject: Re: Exact type
>But allowing the other COMMON subtypes would makes programs non portable:
>The list of subtypes of a type is implementation dependent. We say (page
>1-14) that individual implementation can add additional subclass
>relationships as long as they don't violate CLtL.
But the subtype relationships in CLtL must still hold. Thus, any
importabilities will be the result of importabilites in the Common
Lisp type system, not in the CLOS addition. Reading the rules on
pg. 33-35, it's difficult to discern importabilities, but, talking
to Gregor (who has some experience in this area), they do exist.
However, I think the place to address the problem is to tighten up
the Common Lisp type system, not restrict EXACT-TYPE.
I don't think it's a problem with the CLtL type system. Implementations
can always specialize a built-in type without breaking the portability
of program relying on TYPEP and SUBTYPEP. However it can break the
portability of code relying on EXACT-TYPE. The user shouldn't expect
that an argument will be exactly of this built-in type. On some
machines, you cannot expect an cons cell argument to be always of the
exact type CONS.
While I don't particularly agree with this policy, I think that it gives
implementations so much latitude already that restricting EXACT-TYPE would
be inappropriate.
My way of restricting EXACT-TYPE would prevent the user from expecting
things he cannot always get.
I still think EXACT-TYPE makes sense for user defined type though.
Patrick.
∂29-Sep-87 1935 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Various Topics Discussed Last Week
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:34:52 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae11869; 29 Sep 87 20:12 EDT
Received: from csl.ti.com by RELAY.CS.NET id af14445; 29 Sep 87 19:58 EDT
Received: from dsg by tilde id AA17934; Tue, 29 Sep 87 17:23:19 CDT
Received: From Jenner By dsg Via TCP With SMTP; Tue, 29 Sep 87 14:44:19 CDT
Message-Id: <2768930774-5708656@Jenner>
Date: Tue, 29 Sep 87 14:26:14 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Various Topics Discussed Last Week
In-Reply-To: Msg of Mon, 28 Sep 87 17:05 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 28 Sep 87 17:05 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Various Topics Discussed Last Week
Date: Mon, 28 Sep 87 09:42:29 MST
From: kempf%hplabsz@hplabs.HP.COM
2) On blocks in methods:
I agree that Alternative 1 would be best. Users who want something
different can either use a :AROUND method, as Moon suggested, or
program their own generic function dispatching function, using
the metaobject protocol.
Since we all seem to be agreed on this, I added the following to my
clos-decisions file, which can be used as a resource to make sure
we don't forget to document this decision:
2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded
by an implicit block named -name-, if that is a symbol, or -name1-, if
-name- is (SETF -name1-), by analogy with DEFUN. The same applies to
methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET,
GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around
the body of a method defined by the :METHOD option to GENERIC-FUNCTION.
Dissenters speak now.
I agree with this.
7) On NEXT-METHODS:
The primary reason is for being able to tell if calling CALL-NEXT-METHOD
would signal an error. I understand Masinter's concern, and wonder if
perhaps it might not be better to handle this with Ken Pitman's error
proposal. Other than finding out whether a call to CALL-NEXT-METHOD is
valid, there isn't much use for the list of next methods, as Masinter
has pointed out.
I have no real opinion on this, but we could change this to NEXT-METHOD,
which returns the method object that CALL-NEXT-METHOD would call if
there is one, and returns NIL if CALL-NEXT-METHOD would signal the
no-more-methods error. Then we wouldn't have to worry about the
implications of consing, rplac'ing, and looking at the list.
I don't have objections to that, we could even make it a predicate,
NEXT-METHOD-P returns T if there is a next method, and NIL otherwise.
Patrick.
∂29-Sep-87 1939 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Revised draft of object creation proposal
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:39:03 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa11959; 29 Sep 87 20:18 EDT
Received: from csl.ti.com by RELAY.CS.NET id ap14445; 29 Sep 87 20:01 EDT
Received: from dsg by tilde id AA17961; Tue, 29 Sep 87 17:24:06 CDT
Received: From Jenner By dsg Via TCP With SMTP; Tue, 29 Sep 87 14:44:31 CDT
Message-Id: <2768931638-5760531@Jenner>
Date: Tue, 29 Sep 87 14:40:38 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Revised draft of object creation proposal
In-Reply-To: Msg of Mon, 28 Sep 87 14:14 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Mon, 28 Sep 87 14:14 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Revised draft of object creation proposal
This version differs from the previous one I mailed out only in some
small corrections based on comments received in the mail. The terminology
has been changed back from "named argument" to "keyword argument."
It may be about time to start converting this to the text that will go
into the specification document. Any more comments first?
Looks OK to me.
Patrick.
∂29-Sep-87 1944 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Redefining Classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:44:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244645; Tue 29-Sep-87 22:45:30 EDT
Date: Tue, 29 Sep 87 22:45 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Redefining Classes
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2768937098-6088589@Jenner>
Message-ID: <870929224517.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 29 Sep 87 16:11:38 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
Date: Mon, 28 Sep 87 22:18 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
For these reasons, I believe it is better to specify that the
slot values are conveyed from the old structure of the instance to
the new structure by the low-level implementation, not by a
user-replaceable method. Thus when the generic function
update-obsolete-instance is called, all slots that existed in the
old class definition, and existed as instance slots in the new
class definition, already have their values, as the same low-level
bits. I can't see any need for even a meta-user to replace this
with something else.
Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same
reasons?
This is not a problem. Since at least March, CHANGE-CLASS has been
documented to convey the slot values before it calls CLASS-CHANGED.
One inconsistency remains: CHANGE-CLASS initializes the newly added
slots from their initforms before calling CLASS-CHANGED, whereas
class redefinition initializes the newly added slots in the default
primary method for UPDATE-OBSOLETE-INSTANCE, last I heard. We probably
ought to make them both work the same way.
I prefer not to put this into a method, because then we have to say
what is the state of those slots when a :BEFORE method is running.
I prefer to have the instance in a completely consistent state before
the user-specializable generic function is called. Others prefer to
put it into a method so it can be replaced with something else. Is
that something people actually would do?
∂30-Sep-87 0936 Moon@STONY-BROOK.SCRC.Symbolics.COM Constructors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 09:36:17 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244977; Wed 30-Sep-87 12:37:07 EDT
Date: Wed, 30 Sep 87 12:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Constructors
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
This is a proposal to add constructors back into CLOS, now that the basic
object creation protocol has been agreed upon.
Note that this proposal has been greatly simplified compared to what was being
discussed last spring. In response to several cogent objections that were
raised, a number of problematic features have been removed and constructors
have been made easier to understand and to use. While these proposed
constructors are somewhat different from the constructors whose usefulness has
been verified by their use in New Flavors, a survey of 242 constructors used
in a variety of Flavors-based programs showed that these CLOS constructors
should meet the needs of those programs, which I am assuming to be in some
sense typical. The only real change to those programs would be the
requirement that any slot to be filled by a constructor must have an initarg,
and I don't think that presents any difficulty.
Survey of 242 constructors for 237 different flavors:
83 with MAKE-INSTANCE-style arguments.
Of the remaining 159 constructors:
140 with required arguments only, 8 also with optional or rest,
11 with keyword arguments. 0 with &aux parameters.
15 take no arguments, 102 only fill slots, 3 also specify area,
39 take initargs.
142 fill slots, of which 0 use the initarg rather than the slot name,
and 85 fill slots that don't have initargs. 103 fill inherited slots.
WHY HAVE CONSTRUCTORS?
(1) A cleaner interface for the caller
It's often appropriate to have a more abstract interface than the one provided
by MAKE-INSTANCE. Providing a constructor as the documented inter-module
interface for making a particular kind of object encourages users of the
interface to think in more abstract, conceptual terms. Using a constructor
also allows more aspects of the implementation to be changed without changing
the interface: the class name and initarg names could be changed, or the data
representation could be changed to a DEFSTRUCT representation or a
standard-type, without changing the interface. The constructor could even be
replaced by an interface function that does some complex computations to
decide what type of object to create, or to decide whether to return an
existing object or create a new one.
These needs could be met simply by defining constructor functions with DEFUN
and advertising them. Some reasons to have a :CONSTRUCTOR option in
DEFCLASS are
- to make it easier and more convenient for users to create constructors
- to be culturally consistent with DEFSTRUCT
- :CONSTRUCTOR is a convenient abbreviation for something you could do yourself
in a more long-winded way, just like :ACCESSOR
Other reasons appear below.
(2) Coordination with class redefinition
As the bridge between an external interface and the internal structure of a
class, a constructor function contains certain information about the class,
such as what are its initargs and their default values. When a class is
redefined, any constructors for the class and its subclasses should be updated
if necessary to keep them consistent with the class. Making this updating
automatic is a convenience for programmers, so they don't have to remember to
do it by hand. One way to make the updating automatic would be to add a new
feature to the programming environment by which a linkage could be established
between a function and a class so that redefining the class makes some edits
to the source of the function and then recompiles it. A much simpler way is
to make the constructor syntactically part of the DEFCLASS, so it naturally
gets updated at the same time as the rest of the DEFCLASS. This is another
way in which constructors are analogous to accessors.
(3) More efficient than MAKE-INSTANCE
MAKE-INSTANCE must operate by interpreting data structures that describe the
class, while constructors can be compiled, since they know the exact class
that they are constructing, and since they can be automatically recompiled if
the class or any of its superclasses changes. Initialization methods can be
completely inlined into a constructor, where MAKE-INSTANCE has to go through a
generic function dispatch. Constructors can take positional arguments, which
are more efficient in most implementations, while MAKE-INSTANCE requires
keyword arguments.
Gregor has argued that calls to MAKE-INSTANCE with a constant first argument
can be equally optimized, since the exact class being constructed is known.
While this is true in theory, it seems that either a complicated mechanism
would be needed to make sure that the function was recompiled when the class
was redefined in a way that invalidated the inline code, or else there would
have to be user-visible declarations to control the tradeoff between
performance and robustness in the face of class redefinition. Alternatively,
calls to MAKE-INSTANCE with a constant first argument could be turned into
calls to a constructor function that was created behind the scenes. Then if
the class was redefined, only the constructor function would have to be
recompiled. In either case, if we are going to have this type of mechanism, I
would much rather make it explicitly visible as a :CONSTRUCTOR option than
have it operating behind the scenes in some vaguely defined way.
WHY GET RID OF CONSTRUCTORS?
(1) Simplicity
If we have both constructors and MAKE-INSTANCE, then we have two ways to
do the same thing.
[But CLOS very often provides both a primitive mechanism and a convenient
abbreviation for a common case of using that mechanism.]
The rules for mapping constructor parameter names into slots and initargs are
complicated and confusing.
[Very true. In this proposal they have been enormously simplified.]
(2) Avoid hiding mechanisms
Constructors contain a hidden performance optimization, in that there is
more inlining in their bodies than can be achieved through documented
mechanisms elsewhere.
[I argued above that this is preferable to the inherent complexity of
making that mechanism generally available. Of course there is nothing
to stop us from documenting it if that's what we really want.
Also, exactly the same thing could be said about :ACCESSOR, at least
in the Symbolics implementation.]
(3) Not more efficient than MAKE-INSTANCE
(see discussion above)
SYNTAX
The DEFCLASS option (:CONSTRUCTOR -symbol-) creates a function named -symbol-
that takes the initargs of this class as keyword arguments and returns an
instance of this class. Thus a call to -symbol- looks just like a call to
MAKE-INSTANCE with the first argument omitted.
The DEFCLASS option (:CONSTRUCTOR -symbol- -constructor-lambda-list-) creates
a function named -symbol- whose lambda-list is -constructor-lambda-list-. The
function returns an instance of this class, initialized according to the
parameters in -constructor-lambda-list-. Each parameter supplies the value of
one initarg, determined by the following rules:
- If a parameter variable name is EQ to an initarg name, the parameter
supplies the value of that initarg.
- If a parameter variable name is not EQ to any initarg name, but the symbol
in the keyword package with the same name as the parameter variable
name is EQ to an initarg name, the parameter supplies the value of that
initarg.
- If neither rule succeeds, signal an error.
The second rule exists because initarg names are often keyword symbols, which
are not valid as variable names.
-constructor-lambda-list- allows all of the standard lambda-list features that
DEFUN allows. The only difference is that if no initform is specified for an
&optional, &key, or &aux parameter, instead of just defaulting to NIL, the
parameter defaults in a special way, as in DEFSTRUCT constructors. An
&optional or &key parameter with no initform defaults to the corresponding
initarg's default-initarg form, or if there is none defaults to NIL but is
not passed to initialization methods if unsupplied.
An &aux parameter with no initform defaults to NIL but always behaves as if
unsupplied: the corresponding initarg is not passed to initialization methods
and if there is a default-initarg form, it is never evaluated. (This feature
comes from DEFSTRUCT. Since &aux was never used in constructors in the
Flavors programs I surveyed, I wouldn't propose it if DEFSTRUCT hadn't already
introduced it into Common Lisp.)
The :CONSTRUCTOR option can appear more than once in a DEFCLASS form.
PROCEDURAL DEFINITION OF CONSTRUCTORS
After receiving and defaulting its arguments, a constructor forms an initarg
list from its parameters and calls MAKE-INSTANCE with the appropriate class
object as the first argument and the initarg list as the remaining arguments.
The actual code compiled for a constructor can be optimized in
implementation-dependent ways, as long as it has the same effect as above.
For example, instead of calling MAKE-INSTANCE, the constructor can inline the
body of MAKE-INSTANCE and the bodies of some or all of the methods that
MAKE-INSTANCE calls. This implies that the initarg list might not be fully
materialized, parameter values might really be stored directly into slots, and
keyword argument processing might be completely eliminated. Any optimization
of this type is valid as long as the same effect as calling MAKE-INSTANCE is
achieved and the compiled code is updated when the class or a superclass is
redefined or a relevant method is added or removed.
WHEN ARE CONSTRUCTORS DEFINED AND REDEFINED?
A constructor for a class C cannot be accurately defined until each of
C and its superclasses is defined and all applicable INITIALIZE-INSTANCE
and ALLOCATE-INSTANCE methods have been defined. Until then, the set
of initargs and default-initarg forms is not known.
The macro-expansion of DEFCLASS includes a DEFUN for each constructor
based on the information available at the time DEFCLASS is expanded. If any
superclass is not yet defined, this constructor is a dummy that simply signals
an error. At any later time when C is redefined, a superclass of C is defined
or redefined, or a relevant method is added or removed, CLOS considers each
constructor for C and if necessary recompiles it. If a class is redefined and
a :CONSTRUCTOR is removed, FMAKUNBOUND is applied to the former constructor's
name. Thus a constructor is always up to date with the latest information
about its class.
Note that a user might extract the constructor function from the function
definition of its name, redefine the class (thus redefining the constructor),
and then call the out of date constructor function. Implementations should be
robust in the face of this, either signalling an error when an out of date
constructor function is called, automatically calling the latest version of
the constructor function, or making an instance of the class as it used to be
defined and then updating it as if the class had been redefined after the
instance was made. This follows from the principle that optimization of a
constructor function should not affect its semantics.
This is better than the way Flavors does it, which involves only creating
constructors in COMPILE-FLAVOR-METHODS.
PRIMITIVES FOR MAKING CONSTRUCTORS
At the meta-object level, there will be primitive functions for turning a
constructor lambda-list into a function by filling in parameter defaults and
computing the function body, verifying that a constructor is still valid, and
establishing and removing the linkage between a class and a constructor. A
default method for some function that gets called when things are redefined
will call these functions, to keep the constructors up to date.
Very roughly, these will be:
MAKE-CONSTRUCTOR class name &optional constructor-option-second-argument
-> lambda-expression form
To install the constructor function, evaluate
(PROGN (SETF (SYMBOL-FUNCTION 'name) #'lambda-expression)
form
(LINK-CONSTRUCTOR 'class 'name T)
'name)
VERIFY-CONSTRUCTOR class name &optional constructor-option-second-argument
-> Boolean
LINK-CONSTRUCTOR class name on-or-off
We could also expose the next level down, which defines how class and
constructor-option-second-argument are turned into information that is
compared by VERIFY-CONSTRUCTOR to see whether the constructor needs to be
regenerated, and defines how the form returned by MAKE-CONSTRUCTOR as its
second value records this information. (This form is a bit of a crock. In
the Symbolics system, it isn't necessary, because all information is in the
lambda-expression and in the compiled-function object compiled from it.
However, I'm assuming that some implementations cannot do this, and therefore
provision is needed to associate this information with the name of the
constructor rather than with the actual function object. If we can get rid of
this, great. Of course LINK-CONSTRUCTOR still needs the name so class
redefinition knows where to store the updated constructor.)
∂30-Sep-87 1316 kempf%hplabsz@hplabs.HP.COM Re: Exact type
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:15:51 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 13:16:01 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 13:15:42 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Wed, 30 Sep 87 14:16:39 pdt
To: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Exact type
X-Mailer: mh6.5
In-Reply-To: Your message of Tue, 29 Sep 87 16:12:46 -0500.
<2768937166-6092662@Jenner>
Date: Wed, 30 Sep 87 14:16:36 MST
Message-Id: <9580.560031396@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> The user shouldn't expect
> that an argument will be exactly of this built-in type. On some
> machines, you cannot expect an cons cell argument to be always of the
> exact type CONS.
>
Now I think I understand. We're coming from two different directions,
as far as typing is concerned. Your direction seems to be the structural
equivalence one, that is, two data items are of the same exact type
if they have the same structure. My direction is operator equivalence,
two items have the same exact type if you can apply the same set of operators
to them. As to which is better, I think this may be a religious issue,
so I won't push on it. Both approaches have advantages and disadvantages,
but the advantages of the operator equivalence approach are mostly in
the ability to do compile time optimizations (which is what I had in
mind as a use for EXACT-TYPE) that are particularly important on
conventional machines. Since Common Lisp takes no stand on this issue,
it's open for implementors to do as they feel is best (hiding the
details under TYPEP and SUBTYPEP).
I'll rewrite the Cleanup Committee submission to reflect the restriction
you requested (unless I hear other objections), but I'd suggest we change
the name back to EXACT-CLASS, since the built-in types are no longer
covered.
jak
∂30-Sep-87 1326 kempf%hplabsz@hplabs.HP.COM Re: Various Decisions
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:26:01 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 13:26:22 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 13:26:05 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Wed, 30 Sep 87 14:27:02 pdt
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Various Decisions
X-Mailer: mh6.5
In-Reply-To: Your message of 29 Sep 87 15:29:00 -0700.
Date: Wed, 30 Sep 87 14:26:58 MST
Message-Id: <9637.560032018@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
> On condition handlers instead of NEXT-METHOD:
> Similarly, if it is the case (and I think it likely) that a programmer
> frequently wants to CALL-NEXT-METHOD when there might not be one, then he
> will likely want to write:
> (when (next-method) (call-next-method))
> or use a non-error-signaling version of CALL-NEXT-METHOD rather than
> program a condition handler.
I guess one could make an analogy with function calling. The programmer
can either test if the function is bound before calling:
(if (fboundp 'foo)
(apply foo arglist))
or go ahead and call it and take the exception if it's not:
(catch-condition unbound-function &body (apply foo arglist))
So I guess it makes sense to have a way of checking if CALL-NEXT-METHOD
is "bound" within the method, in addition.
NEXT-METHOD-P, returning T or NIL, is fine with me.
jak
∂30-Sep-87 1410 Moon@STONY-BROOK.SCRC.Symbolics.COM Should redefining a class reinitialize shared slots?
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 14:10:06 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245367; Wed 30-Sep-87 17:10:57 EDT
Date: Wed, 30 Sep 87 17:11 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Should redefining a class reinitialize shared slots?
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870929-085934-1876@Xerox>
Message-ID: <870930171107.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 29 Sep 87 08:59 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I haven't been able to figure out what you mean here. Editing
out the parts of your comment I don't understand leaves "Redefining
the class should set the value of the class slots", which we've
never said before and I don't think I agree with. Here are two
cases to think about:
(1) A class slot whose value is a list of all the instances,
initialized to nil when the class is first defined and updated by
an initialize-instance method.
(2) A class slot whose value is the price of an instance,
initialized by :initform in the defclass.
In case 1, you surely don't want the slot value reset to nil
when you redefine the class. In case 2, you might want to set the
price to the new value of the :initform. If redefining a class
always reinitializes class slots, you can't do case 1. If it never
reinitializes class slots, you can work around case 2 by doing setf
of slot-value at the same time as you redefine the class.
These are interesting examples, and cause one to ponder.
I think the difference here is like the difference between
editing a function definition on a file and
editing the actual function list structure with a structure editor.
Changing a function using a structure editor affects existing calls, and
editing the file cannot.
I think that's a good analogy.
Although, which existing calls are actually affected by changing a function
with a structure editor probably depends a lot on what in the function you
change, versus where in the function control is suspended, and also on
implementation-dependent details such as whether you compile or not.
Maybe that's part of the applicability of the analogy, though, in the
sense that the issue never seems to be simple. Bring back APL\360, where
editing a function automatically invalidated any activation records for
that function, and announced "SI DAMAGE".
I think the corresponding cases for classes are:
use the metaobject protocol to update an existing class using the slot
objects that currently exist,
and reevaluating the defclass form.
In the latter case, the specification only guarantees that class
objectsame object identity is preserved,
Well, what the specification actually says (87-002 page 1-12, very top
of the page, sentence actually starts on the preceding page) is that
values of class slots are preserved. So the issue is whether we want
to change the specification. I think the specification now says that
re-evaluating a defclass form is not like re-evaluating a defun form,
but is more like structure editing: it patches an existing object
rather than creating a new object.
unless we want to go more into
a DWIM mode, that is guess which items in the new definition are meant
to yield the same result as the old case.
The DWIM idea doesn't appeal to me since I can't figure out how to make
it predictable.
It seems to me the only predictable rules are:
(1) all class slots retain their values when the class is redefined.
(2) all class slots are reinitialized when the class is redefined.
I prefer rule 1 because it is analogous to the rule for instance slots.
Also, it's easier to reinitialize a slot that was retained than to
retain a slot that was reinitialized, if a user wants to implement
behavior different from the default.
Revisiting in this light the rules for slots whose allocation is changed:
class -> instance copies the slot value into each instance, again
by analogy with the rule for instance slots (the value returned
by SLOT-VALUE remains the same).
instance -> class reinitializes the slot, because there is no
distinguished instance from which to get the value.
∂30-Sep-87 1353 Moon@STONY-BROOK.SCRC.Symbolics.COM Slot Inheritance
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:53:32 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245353; Wed 30-Sep-87 16:54:29 EDT
Date: Wed, 30 Sep 87 16:54 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Slot Inheritance
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <3388.559949911@hplabsz>
Message-ID: <870930165439.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 29 Sep 87 15:38:31 MST
From: kempf%hplabsz@hplabs.HP.COM
> REVISED ``INHERITANCE OF SLOTS AND SLOT OPTIONS'' SECTION:
This looks good to me, with the proviso that "shared slot" be replaced
by whatever terminology we decide on. After reading through it,
I can't find any ambiguity in the wording. The reference to :DYNAMIC
slots needs to be removed, however.
Right. The one I mailed out is identical, except for TEX commands, to
what was handed out at the March X3J13 meeting, I believe. When put into
the document it should need some minor editing to match the current
state of the spec. I checked it again and found only the removal of
:DYNAMIC and the addition of :INITARG.
It seems to be more concise than the current description.
Thanks.
∂30-Sep-87 1403 RPG NEXT METHOD
To: common-lisp-object-system@SAIL.STANFORD.EDU
JAK writes:
``I guess one could make an analogy with function calling. The programmer
can either test if the function is bound before calling:
(if (fboundp 'foo)
(apply foo arglist))''
One could, but I think it's a bad analogy. Many methods can be written on
a generic function, and it is sensible to suppose that the authors of the
methods on that generic function might desire that his methods each call
the next most specific one - method combination could be used, but assume
not. In this case, the writer of each method will not know, a priori,
whether there will be any other such methods.
Therefore, the author of such a method will be thinking that his method
will call the next most specific one, if it exists. In short, the test of
whether there is such a further method is like the termination test
in a control structure. Hence it is not like an exception.
The author of the code JAK mentions is calling a specific function
by name, and not be relative ``position'' from the current one. Thus,
I regard his analogy as not convincing.
I can support NEXT-METHOD-P, because I doubt there is much constructive
use to which the next method could be put - funcall its method-function (?).
-rpg-
∂30-Sep-87 1419 Moon@STONY-BROOK.SCRC.Symbolics.COM NEXT METHOD
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 14:19:31 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245381; Wed 30-Sep-87 17:20:30 EDT
Date: Wed, 30 Sep 87 17:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: NEXT METHOD
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Sep 87 17:03 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870930172036.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Sep 87 1403 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I can support NEXT-METHOD-P, because I doubt there is much constructive
use to which the next method could be put - funcall its method-function (?).
Let's go with NEXT-METHOD-P. It sure seems to duck a lot of problems.
∂30-Sep-87 1521 RPG Should redefining a class reinitialize shared slots?
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``It seems to me the only predictable rules are:
(1) all class slots retain their values when the class is redefined.
(2) all class slots are reinitialized when the class is redefined.''
There is a third option, which would be to specify the redefinition
initialization action in the DEFCLASS as a class slot option (:retain or
:reinitialize, for example).
Moon writes:
``instance -> class reinitializes the slot, because there is no
distinguished instance from which to get the value.''
Well, we could have declarative slot combination, in which these
values could be combined.... (hee, hee).
-rpg-
∂30-Sep-87 1619 Bobrow.pa@Xerox.COM class/instance vs shared/local
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 16:19:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 15:30:51 PDT
Date: 30 Sep 87 15:29 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: class/instance vs shared/local
To: common-lisp-object-system@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870930-153051-2792@Xerox>
I feel strongly about using class and instance rather than shared and
local. If no one else feels strongly, can we agree to go with these so
we can get on with the documentation. (Dick -- you are the only one to
argue against this. Is this OK with you?).
danny
∂30-Sep-87 1619 Bobrow.pa@Xerox.COM Re: next-method-p
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 16:18:56 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 15:11:31 PDT
Date: 30 Sep 87 15:11 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: next-method-p
To:Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870930-151131-2747@Xerox>
I detect a consensus for next-method-p. If I hear no objections, I will
send out a writeup in the next day (and/or Moon can put it in his file
of decisions).
danny
∂30-Sep-87 1719 Moon@STONY-BROOK.SCRC.Symbolics.COM Should redefining a class reinitialize shared slots?
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:19:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245685; Wed 30-Sep-87 20:19:43 EDT
Date: Wed, 30 Sep 87 20:19 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Should redefining a class reinitialize shared slots?
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Sep 87 18:21 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Sep 87 1521 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
``It seems to me the only predictable rules are:
(1) all class slots retain their values when the class is redefined.
(2) all class slots are reinitialized when the class is redefined.''
There is a third option, which would be to specify the redefinition
initialization action in the DEFCLASS as a class slot option (:retain or
:reinitialize, for example).
That's a good point. I could go along with that if we think the extra
complexity is justified.
∂30-Sep-87 1748 kempf%hplabsz@hplabs.HP.COM Re: Should redefining a class reinitialize shared slots?
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:47:52 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 17:47:50 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 17:47:30 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Wed, 30 Sep 87 18:48:27 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Should redefining a class reinitialize shared slots?
X-Mailer: mh6.5
In-Reply-To: Your message of Wed, 30 Sep 87 20:19:00 -0400.
<870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 30 Sep 87 18:48:25 MST
Message-Id: <13275.560047705@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Date: 30 Sep 87 1521 PDT
> From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
> ``It seems to me the only predictable rules are:
> (1> ) all class slots retain their values when the class is redefined.
> (2) all class slots are reinitialized when the class is redefined.''
> There is a third option, which would be to specify the redefinition
> initialization action in the DEFCLASS as a class slot option (:retain or
> :reinitialize, for example).
> That's a good point. I could go along with that if we think the extra
> complexity is justified.
No. I think 2) is sufficient.
jak
∂30-Sep-87 1756 Bobrow.pa@Xerox.COM Re: Should redefining a class reinitialize shared slots?
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:56:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 17:30:45 PDT
Date: 30 Sep 87 17:30 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Should redefining a class reinitialize shared slots?
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 30 Sep 87 17:11 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870930-173045-3035@Xerox>
It seems to me the only predictable rules are: (1) all
class slots retain their values when the class is redefined. (2)
all class slots are reinitialized when the class is redefined.
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
Despite the fact that I think I would usually want to retain current
values of class slots, I worry about a confusion of models for the user.
Rule 2 is a pure text based model; Rule 1 is a semi-structural model.
This leads to questions about what changes in a class slot cause it to
get reinitialized?
If I change the :type
If I change the :initform
If I change its order in the list of slots
If I add another class slot before it in the list
If I change its name
If one were doing structural editing, then none of these would cause
reinitialization (even a name change). When dealing with the defclass
form as text, the answer is less clear -- even with respect to the name
change i.e. consider changing to "all-instances" from
"all-my-instances" or from "allinstances".
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
I find these arguments strong, but still find rule 2 is most consistent.
Rule 1 probably is desirable in most cases, but I think will be
confusing when we consider the above cases -- again, shades of DWIM. My
intuition is not strong on this, so I would like to see opinions from
Gregor and Patrick (others too, of course).
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
RPG writes:
There is a third option, which would be to specify the
redefinition initialization action in the DEFCLASS as a class slot
option (:retain or :reinitialize, for example).
I don't think additional language features are useful here; in
particular, I would hate to see options specified that depended on the
value(s) of other option(s). I think we must make up our mind what
model to be supported.
∂30-Sep-87 2045 Moon@STONY-BROOK.SCRC.Symbolics.COM Amendments requiring additional writing
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 20:44:43 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245796; Wed 30-Sep-87 23:45:30 EDT
Date: Wed, 30 Sep 87 23:45 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Amendments requiring additional writing
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870925214129.4.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870928-133654-19356@Xerox>,
<870928184306.6.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870929-085934-1876@Xerox>,
<870929-180832-1165@Xerox>,
<870930171107.8.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870930171528.9.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 30 Sep 87 18:21 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<870930-152906-2790@Xerox>,
<870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870930-173045-3035@Xerox>,
<13275.560047705@hplabsz>
Message-ID: <870930234533.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here is a replacement for pages 1-11 and 1-12, based on the referenced
mail and the latest CONCEP.TEX on SAIL. I offered to write this because
it incorporates an amended paragraph I sent out on 25 Sep, and because
Danny asked me to write it because he said he was too busy to do any
writing.
Note that we will probably want a separate section explaining how to
change the class of an object, using change-class. Note that
class-changed and update-instance-structure are currently incompatible
with respect to who evaluates the initforms; one of them has to be
changed. I didn't attempt to write anything for change-class. We
could always describe change-class only in the Function chapter, and
not have a Concept section for it.
I have not changed any local/shared/instance/class slot terminology.
We can change that later if we agree on the new terminology.
\beginSection{Redefining Classes}
When a {\bf defclass} form is evaluated and a class with the given
name already exists, the existing class is redefined. Redefining a
class modifies the existing class object to reflect the new class
definition; it does not create a new class object for the class. Any
method created by an {\bf :accessor} or {\bf :reader}
option specified by the old
{\bf defclass} form is removed from the corresponding generic
function unless that same method is specified by the new {\bf
defclass} form; any function specified by the {\bf :constructor}
option of the old {\bf defclass} form is removed from the
corresponding symbol function cell.
When the class $C$ is redefined, changes are propagated to instances
of it and to instances of any of its subclasses. The updating of an
instance whose class has been redefined (or any of whose superclasses
have been redefined) occurs at an implementation-dependent time, but
no later than the next time a slot of that instance is read or written.
Updating an instance does not change its identity as
defined by the {\bf eq} function. The updating process may change the
slots of that particular instance, but it does not create a new
instance. Whether updating an instance consumes storage is
implementation dependent.
If a class is redefined in such a way that the set of local slots
accessible in an instance of the class is changed or the order of slots
in storage is changed, the function {\bf update-instance-structure} is
called whenever an instance of the class is updated, to complete the
transformation from the old representation of the instance to the new
representation. Implementations may choose to invoke
{\bf update-instance-structure} under other circumstances as well.
Programmers can define methods for {\bf update-instance-structure} to
specify actions to be taken when an instance is updated. When
{\bf update-instance-structure} is called, the structure of the instance
has already been converted to conform to the new class definition,
and newly added slots are uninitialized.
Note that redefining a class may cause slots to be added or deleted.
When an instance is updated, new slots are initialized and the
values of deleted slots are discarded. Each local slot of the new
version of the class with no slot by the same name in the old version
of the class is initialized to the value of the corresponding {\bf
:initform} option of the new class or remains uninitialized if the new
version of the class does not specify or inherit the {\bf :initform} option for
that slot. This is the same as the initialization
done by {\bf make-instance} except that no initialization methods are
invoked and no {\bf make-instance} initialization arguments are
present. This initialization is performed by the default primary
method for {\bf update-instance-structure}.
\eject
If in the new version of the class there is a local slot of the same
name as any slot in the old version of the class, the value of that
slot is unchanged. This is true regardless of whether the old slot
was a local slot or a shared slot. This means that if the slot
has a value, the value returned by {\bf slot-value} after
class redefinition is {\bf eql} to the value returned by {\bf
slot-value} before class redefinition. Similarly, if the
slot was uninitialized, it remains uninitialized.
If in the new
version of the class there is a shared slot of the same name as any
shared slot in the old version of the class, the value of that slot
is unchanged. If in the new version of the class there is
a shared slot of the same name as any local slot in the old version of
the class, that shared slot is initialized to the value of the
corresponding {\bf :initform} option of the new class or remains
uninitialized if the new version of the class does not specify or
inherit the {\bf :initform} option for that slot. Shared slots
are updated at the moment of class redefinition and
are not affected by the updating of an instance nor by the
values of any local slots.
The \CLOS\ guarantees that {\bf defclass} can be used to change the
definition of an existing class that was previously defined by {\bf
defclass} as long as the {\bf :metaclass} option is not used in either
the old or the new definition. Whether {\bf defclass} is allowed to
change the metaclass and whether redefining a class causes existing
instances to be updated is up to the implementor of the particular
metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to
control this.
\endSection%{Redefining Classes}
∂30-Sep-87 2352 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/local;class/instance
Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 30 Sep 87 23:52:50 PDT
Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP
id AA29175; Thu, 1 Oct 87 02:53:17 EDT
Received: by mcvax.cwi.nl; Thu, 1 Oct 87 06:31:49 +0100 (MET)
Received: by inria.inria.fr; Wed, 30 Sep 87 22:56:32 +0100 (MET)
Date: Wed, 30 Sep 87 22:56:32 +0100
From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe)
Message-Id: <8709302156.AA16490@inria.inria.fr>
To: Bobrow.pa@xerox.com, RPG@sail.stanford.edu
Subject: Re: Shared/local;class/instance
Cc: common-lisp-object-system@sail.stanford.edu
I strongly believe that :shared is a better name than :class.
As a Smalltalk teacher i have big troubles with the Smalltalk non-symmetry
between class/instance methods and class/instance variables.
My (Smalltalk) point of view is that class variables should refer the
instance variables of a class treated as an object.
∂01-Oct-87 0822 Bobrow.pa@Xerox.COM Re: Shared/local;class/instance
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:21:56 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 08:22:24 PDT
Date: 1 Oct 87 08:22 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Shared/local;class/instance
In-reply-to: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe)'s
message of Wed, 30 Sep 87 22:56:32 +0100
To: mcvax!inria.inria.fr!cointe@uunet.UU.NET
cc: Bobrow.pa@Xerox.COM, RPG@sail.stanford.edu,
common-lisp-object-system@sail.stanford.edu
Message-ID: <871001-082224-3610@Xerox>
I strongly believe that :shared is a better name than :class.
As a Smalltalk teacher i have big troubles with the Smalltalk
non-symmetry between class/instance methods and class/instance
variables. My (Smalltalk) point of view is that class variables
should refer the instance variables of a class treated as an object.
What should the other one be called. Would you prefer shared/instance?
danny
∂01-Oct-87 0834 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:34:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 08:35:08 PDT
Date: 1 Oct 87 08:35 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Amendments requiring additional writing
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 30 Sep 87 23:45 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <871001-083508-3628@Xerox>
I mostly agree. I notice consturctors still in there, although that is
not yet agreed to. But the oner serious remaining problem is in the
wording of the last paragraph (not a new one):
The \CLOS\ guarantees that {\bf defclass} can be used to change
the definition of an existing class that was previously defined by
{\bf defclass} as long as the {\bf :metaclass} option is not used
in either the old or the new definition. Whether {\bf defclass} is
allowed to change the metaclass and whether redefining a class
causes existing instances to be updated is up to the implementor of
the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will
describe how to control this.
The problem is that defclass without a metaclass option can be used with
class-for-redefinition to keep the class other than standard-class. I
would prefer to say:
The \CLOS\ guarantees that the user can change
the definition of an existing class that is a standard-class,
and cause its instances to be updated.
Whether redefining a class that is not a standard-class
causes existing instances to be updated is up to the implementor of
the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will
describe how to control this.
∂01-Oct-87 0836 kempf%hplabsz@hplabs.HP.COM Re: Amendments requiring additional writing
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:36:46 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 08:36:23 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 08:36:05 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 1 Oct 87 09:37:02 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Amendments requiring additional writing
X-Mailer: mh6.5
In-Reply-To: Your message of Wed, 30 Sep 87 23:45:00 -0400.
<870930234533.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 01 Oct 87 09:36:59 MST
Message-Id: <21559.560101019@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Here is a replacement for pages 1-11 and 1-12, based on the referenced
> mail and the latest CONCEP.TEX on SAIL. I offered to write this because
This looks OK to me. We'll need a specification for
UPDATE-INSTANCE-STRUCTURE in addition, for Section 2.
jak
∂01-Oct-87 0838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Should redefining a class reinitialize shared slots?
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:38:43 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 246119; Thu 1-Oct-87 11:39:32 EDT
Date: Thu, 1 Oct 87 11:39 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Should redefining a class reinitialize shared slots?
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870930-173045-3035@Xerox>
Message-ID: <871001113935.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Sep 87 17:30 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
It seems to me the only predictable rules are: (1) all
class slots retain their values when the class is redefined. (2)
all class slots are reinitialized when the class is redefined.
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
Despite the fact that I think I would usually want to retain current
values of class slots, I worry about a confusion of models for the user.
Rule 2 is a pure text based model; Rule 1 is a semi-structural model.
This leads to questions about what changes in a class slot cause it to
get reinitialized?
If I change the :type
If I change the :initform
If I change its order in the list of slots
If I add another class slot before it in the list
If I change its name
If one were doing structural editing, then none of these would cause
reinitialization (even a name change). When dealing with the defclass
form as text, the answer is less clear -- even with respect to the name
change i.e. consider changing to "all-instances" from
"all-my-instances" or from "allinstances".
The rule that CLOS has been using all along is that slot identity is
determined entirely by the slot's name. It seems to me that this is
visible in many places throughout CLOS. This means that the only edit
that causes a class slot to get reinitialized is changing its name
(it's not really meaningful to say the slot gets reinitialized in this
case; rather, one slot is deleted and a new one is created and initialized).
Changing any other attribute of the slot does not affect the slot's
identity (with the one unfortunate exception that changing the allocation
from instance to class (a.k.a. from local to shared) destroys the slot
and creates and initializes a new slot).
I think bringing in notions of editors of various types may actually only
confuse the issue. After all, the semantics of classes in CLOS are defined
in terms of the behavior of certain objects under certain operations, and
are not tied to the syntax of the DEFCLASS form, right? DEFCLASS is only
the most convenient way to define a class, not the only way.
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
I find these arguments strong, but still find rule 2 is most consistent.
Rule 1 probably is desirable in most cases, but I think will be
confusing when we consider the above cases -- again, shades of DWIM. My
intuition is not strong on this, so I would like to see opinions from
Gregor and Patrick (others too, of course).
I vehemently disagree with the notion that rule 2 is consistent with the
rest of CLOS.
I prefer rule 1 because it is analogous to the rule for
instance slots. Also, it's easier to reinitialize a slot that was
retained than to retain a slot that was reinitialized, if a user
wants to implement behavior different from the default.
RPG writes:
There is a third option, which would be to specify the
redefinition initialization action in the DEFCLASS as a class slot
option (:retain or :reinitialize, for example).
I don't think additional language features are useful here; in
particular, I would hate to see options specified that depended on the
value(s) of other option(s). I think we must make up our mind what
model to be supported.
I agree with this. We should only adopt this third option if it becomes
clear that it solves problems that we need to solve and that neither of
the other two options can cope with.
∂01-Oct-87 0901 kempf%hplabsz@hplabs.HP.COM CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:01:40 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 09:02:06 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 09:01:42 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 1 Oct 87 10:02:39 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
X-Mailer: mh6.5
Date: Thu, 01 Oct 87 10:02:35 MST
Message-Id: <22064.560102555@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Aren't these generic functions essentially doing the same thing?
I understand that a user wanting to smash an instance needs a
generic function (CHANGE-CLASS) which would change the structure
of the instance to reflect the new class, and initialize, but
why have two ways of updating the new instance? The point of
UPDATE-OBSOLETE-INSTANCE is to give a user hook into transferring
information from the old instance to the new, and that seems
also to be the point of CLASS-CHANGED. I agree that, in the case
of UPDATE-OBSOLETE-INSTANCE, the class object and name are the
same for the old and new instance, while, in the case of CLASS-CHANGED,
this is not the case. But the semantic delta here seems very minor,
since, in both cases, by the time the respective generic function
gets the instance, the structure has changed. The only difference
is how the information on the old instance is transferred to the
generic function. In the case of UPDATE-OBSOLETE-INSTANCE, it is
through lists of slots and their values, while through CLASS-CHANGED,
it seems to be through a copy of the old instance.
Why not simply replace CLASS-CHANGED? Am I missing something?
jak
∂01-Oct-87 0911 Moon@ALLEGHENY.SCRC.Symbolics.COM Re: Amendments requiring additional writing
Received: from [128.81.41.45] by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:11:01 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by ALLEGHENY.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 65682; Thu 1-Oct-87 11:51:05 EDT
Date: Thu, 1 Oct 87 11:50 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Amendments requiring additional writing
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871001-083508-3628@Xerox>
Message-ID: <871001115040.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 1 Oct 87 08:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I mostly agree. I notice consturctors still in there, although that is
not yet agreed to. But the oner serious remaining problem is in the
wording of the last paragraph (not a new one):
The \CLOS\ guarantees that {\bf defclass} can be used to change
the definition of an existing class that was previously defined by
{\bf defclass} as long as the {\bf :metaclass} option is not used
in either the old or the new definition. Whether {\bf defclass} is
allowed to change the metaclass and whether redefining a class
causes existing instances to be updated is up to the implementor of
the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will
describe how to control this.
The problem is that defclass without a metaclass option can be used with
class-for-redefinition to keep the class other than standard-class. I
would prefer to say:
The \CLOS\ guarantees that the user can change
the definition of an existing class that is a standard-class,
and cause its instances to be updated.
Whether redefining a class that is not a standard-class
causes existing instances to be updated is up to the implementor of
the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will
describe how to control this.
I can't see any difference between these two paragraphs, except that your
suggested replacement is less direct, because the reader has to turn elsewhere
to find out what a standard-class is. As far as I can tell there are no
programs that would work under the first paragraph but not under the second.
However, I continue to have almost no opinion on metaclass issues until I
have seen a description of metaclasses that I can understand.
∂01-Oct-87 0925 kempf%hplabsz@hplabs.HP.COM COERCE (not urgent)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:25:00 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 09:25:23 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 09:24:46 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 1 Oct 87 10:25:42 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: COERCE (not urgent)
X-Mailer: mh6.5
Date: Thu, 01 Oct 87 10:25:39 MST
Message-Id: <22184.560103939@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Since COERCE is a Cleanup Committee issue, there is no urgency to finish
electronic mail discussion for Dick and Linda before next Fri., but I
thought I would post it so that people can start thinking about it.
I'll summarize discussion by Oct. 17.
ISSUE: How should (or even should) COERCE be changed to accommodate
CLOS?
REMARK: CLOS already has two mechanisms of changing an object's class:
1) Class redefinition (largely hidden, automatic, with some
user defined hooks, smashes the instance)
2) CHANGE-CLASS (smashes the instance)
ALTERNATIVES:
1) Leave COERCE as it currently is. That is, make no CLOS
specific changes.
2) Keep COERCE a function and have an internal generic function,
COERCE-USING-CLASS handle coercion when the second argument is
a class object, or the type specifier is for a CLOS class.
3) Make COERCE a generic function, with one method handling coercion
when the second argument is a type specifier and one when it is
a class object. Note that the type specifier method would need to
handle the case of a type specifier for a CLOS class by using SYMBOL-CLASS
to get the class, then reinvoking the generic function.
SEMANTICS FOR CLOS OBJECTS:
COERCE creates a new instance of the second argument, initializing
according to the initialization protocol for the class, and then copies
named slots common between the two instances, modulo type errors.
If the first argument is already of the class indicated by the second
argument, it is returned without copying.
Note that this corresponds roughly with the current semantics when the
first argument is a sequence and the second argument is a subtype
of SEQUENCE.
ALTERNATIVE ADVANTAGES AND DISADVANTAGES:
The advantages of 1) are obvious: no changes needed in the base
Common Lisp. The advantage of 2) is that the class and type specifier
functionality are segregated under different names, since
the new generic function takes care of coercion for CLOS.
The advantage of 3) is that it reduces name proliferation, and integrates
CLOS more tightly into the language. In addition, users can write new
methods which discriminate on the first argument, and take a type
specifier for the second.
The disadvantages of 1) are that users must write their own methods
for coercion. The disadvantage of 2) is that it introduces Yet Another
metaclass function (COERCE-USING-CLASS). The disadvantages of 3) are
that users might do something dangerous with existing type specifiers
(like define a method that coerces an integer into a list).
∂01-Oct-87 0950 Bobrow.pa@Xerox.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:50:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 09:48:33 PDT
Date: 1 Oct 87 09:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 01 Oct 87
10:02:35 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <871001-094833-3815@Xerox>
But the semantic delta here seems very minor, since, in both
cases, by the time the respective generic function gets the
instance, the structure has changed. The only difference is how the
information on the old instance is transferred to the generic
function. In the case of UPDATE-OBSOLETE-INSTANCE, it is through
lists of slots and their values, while through CLASS-CHANGED, it
seems to be through a copy of the old instance.
Why not simply replace CLASS-CHANGED? Am I missing something?
Yes. First, it is possible to specialize class-changed on the basis of
both classes, and secondly, one can use methods on the class of the
first (previous) object e.g.
(defmethod class-changed ((p1 x-y-point) (p2 rho-theta-point))
(with-slots (p2 rho theta)
(setf rho (rho p1)
theta (theta p1))))
(defclass class-changed ((v1 directed-vector) (p rho-theta-point))
...)
∂01-Oct-87 0957 Bobrow.pa@Xerox.COM Re: Amendments requiring additional writing
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:57:44 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 09:53:12 PDT
Date: 1 Oct 87 09:53 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Amendments requiring additional writing
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 1 Oct 87 11:50 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <871001-095312-3834@Xerox>
DGB I would prefer to say:
The \CLOS\ guarantees that the user can change
the definition of an existing class that is a standard-class,
and cause its instances to be updated.
Whether redefining a class that is not a standard-class
causes existing instances to be updated is up to the implementor of
the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will
describe how to control this.
Moon I can't see any difference between these two paragraphs, except
that your suggested replacement is less direct, because the reader
has to turn elsewhere to find out what a standard-class is. As far
as I can tell there are no programs that would work under the first
paragraph but not under the second.
It is exactly this level of indirection I am encouraging because it will
not eventually be misleading. Later caveats about when defclass doesn't
produce standard-classes will not change the correctness of this
paragraph.
∂01-Oct-87 1017 kempf%hplabsz@hplabs.HP.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 10:16:58 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 10:16:36 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 10:16:02 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 1 Oct 87 11:16:49 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
X-Mailer: mh6.5
In-Reply-To: Your message of 01 Oct 87 09:48:00 -0700.
<871001-094833-3815@Xerox>
Date: Thu, 01 Oct 87 11:16:44 MDT
Message-Id: <23927.560107004@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Yes. First, it is possible to specialize class-changed on the basis of
> both classes, and secondly, one can use methods on the class of the
> first (previous) object e.g.
> (defmethod class-changed ((p1 x-y-point) (p2 rho-theta-point))
> (with-slots (p2 rho theta)
> (setf rho (rho p1)
> theta (theta p1))))
>
> (defclass class-changed ((v1 directed-vector) (p rho-theta-point))
> ...)
One could do the same thing as:
(defmethod change-class
((p1 x-y-point) (class (eql (class-named 'rho-theta-point))))
(let
( (p2 (call-next-method)) )
(with-slots (p2 rho theta)
(setf rho (rho p1))
(setf theta (theta p1)))))
(defmethod class-changed
((v1 directed-vector) (class (eql (class-named 'rho-theta-point))))
...
)
∂01-Oct-87 1117 Bobrow.pa@Xerox.COM Can defgeneric provide defaults for &key args
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 11:17:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 10:52:40 PDT
Date: 1 Oct 87 10:52 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Can defgeneric provide defaults for &key args
To: Common-Lisp-Object-System@sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
Message-ID: <871001-105240-3994@Xerox>
Consider the following example of the new regime with lambda list
congruence.
I don't think the rules allow a default value to be specified for a
keyword argument in defgeneric now, even though all methods must accept
such keys? Should it be allowed to support a uniform default?
Example:
(defgeneric width &key (scale-factor 1))
(defmethod width ((s string) &key scale-factor (font *standard-font*))
...)
(defmethod width ((s bitmap) &key scale-factor paint-fn)
...)
The alternative is:
(defgeneric width &key scale-factor)
(defmethod width ((s string)
&key (scale-factor 1)(font *standard-font*))
...)
(defmethod width ((s bitmap)
&key (scale-factor 1) paint-fn)
...)
∂01-Oct-87 1117 Bobrow.pa@Xerox.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 11:17:38 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 11:01:44 PDT
Date: 1 Oct 87 11:01 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 01 Oct 87
11:16:44 MDT
To: kempf%hplabsz@hplabs.HP.COM
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <871001-110144-4013@Xerox>
> Yes. First, it is possible to specialize class-changed on
the basis of
> both classes, and secondly, one can use methods on the class
of the
> first (previous) object e.g.
> (defmethod class-changed ((p1 x-y-point) (p2
rho-theta-point))
> (with-slots (p2 rho theta)
> (setf rho (rho p1)
> theta (theta p1))))
>
> (defclass class-changed ((v1 directed-vector) (p
rho-theta-point))
> ...)
One could do the same thing as:
(defmethod change-class
((p1 x-y-point) (class (eql (class-named 'rho-theta-point))))
(let
( (p2 (call-next-method)) )
(with-slots (p2 rho theta)
(setf rho (rho p1))
(setf theta (theta p1)))))
Two problems with what you say:
1) After the call-next-method p1 is EQL to p2, and p1 is no longer an x y point.
2) Even if this worked, it wouldn't work for a subclass of rho-theta point.
∂01-Oct-87 1244 kempf%hplabsz@hplabs.HP.COM Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 12:44:44 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 12:44:18 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 12:43:38 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 1 Oct 87 13:44:34 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE
X-Mailer: mh6.5
In-Reply-To: Your message of 01 Oct 87 11:01:00 -0700.
<871001-110144-4013@Xerox>
Date: Thu, 01 Oct 87 13:44:31 MDT
Message-Id: <27017.560115871@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> One could do the same thing as:
> (defmethod change-class
> ((p1 x-y-point) (class (eql (class-named 'rho-theta-point))))
> (let
> ( (p2 (call-next-method)) )
> (with-slots (p2 rho theta)
> (setf rho (rho p1))
> (setf theta (theta p1)))))
> Two problems with what you say:
> 1) After the call-next-method p1 is EQL to p2, and p1 is no longer an x y poi
nt.
> 2) Even if this worked, it wouldn't work for a subclass of rho-theta point.
Right. It is pretty gross code anyway.
∂01-Oct-87 1621 RPG Shared/class;instance/local
To: common-lisp-object-system@SAIL.STANFORD.EDU
I agree with Cointe about the intuitiveness of the name ``shared''
versus ``class.'' I agree with Danny about ``instance'' being better than
``local.'' I'm not sure we've come to grips with the real problem, though.
The real problem is the distinction between the CLOS language constructs -
in particular their syntax - and the English we use to describe them.
There is no problem, aside from confusion, with having CLOS provide
for slots with allocation type :class and calling such a slot a shared
slot. For example, we can write a piece of code like this:
(let ((n 0)) #'(lambda () (incf n)))
and describe it as producing a closure, though the string ``closure''
appears nowhere in the piece of code.
One rule of technical writing is to avoid creating names for objects that
are compound nouns where some or all of the nouns are jargon words. The
term ``shared slot'' is a normal English noun phrase because ``shared'' is
a normal English adjective. The term ``class slot'' is a compound jargon
term.
To be blunter about it, if a naive weenie saw the term ``class slot,'' he
might think, ``how nice, a class slot in a mediocre instance!''
The phrase ``:class slot'' is even worse, because ``:class'' is not a word
(this is why you never see LGD and me write ``.... CLASS-CHANGED is a
generic function that....'' but ``The generic function CLASS-CHANGED....''
because in the latter construction ``CLASS-CHANGED'' is used as a name
referred to by the text rather than as a word in it.)
If I were to contemplate rewriting the CLOS specification to use the
term ``class'' where ``shared'' was used before, I would opt for
re-phrasing the noun phrase ``shared slot'' as ``a slot whose allocation
type is :class'' in order to be precise.
-rpg-
∂01-Oct-87 2100 Bobrow.pa@Xerox.COM Re: Shared/class;instance/local
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 21:00:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 21:00:43 PDT
Date: 1 Oct 87 21:00 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Shared/class;instance/local
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Oct 87
16:21 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <871001-210043-4996@Xerox>
I agree with Cointe about the intuitiveness of the name
``shared'' versus ``class.'' I agree with Danny about ``instance''
being better than ``local.''
Certainly a reasonable choice of vocabulary would be shared/instance.
But then I would request that we use :shared, and :instance for the
allocation options.
I'm not sure we've come to grips with the real problem, though.
The real problem is the distinction between the CLOS language
constructs - in particular their syntax - and the English we use to
describe them. There is no problem, aside from confusion, with
having CLOS provide for slots with allocation type :class and
calling such a slot a shared slot.
Yes, it is confusion I would like to avoid, now and with at least some
forseeable extensions. It is simpler to remember to use the descriptive
term rather than a technofied synonym, or even to remember a technofied
if it is used as the descriptive term.
If I were to contemplate rewriting the CLOS specification to
use the term ``class'' where ``shared'' was used before, I would
opt for re-phrasing the noun phrase ``shared slot'' as ``a slot
whose allocation type is :class'' in order to be precise.
In this specification document, perhaps that is what we should do,
whatever vocabulary we settle on. I thought precision was our principal
criterion.
∂02-Oct-87 0942 kempf%hplabsz@hplabs.HP.COM Re: Constructors
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 09:41:53 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Fri, 2 Oct 87 09:41:13 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 2 Oct 87 09:40:28 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 2 Oct 87 10:41:23 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Constructors
X-Mailer: mh6.5
In-Reply-To: Your message of Wed, 30 Sep 87 12:37:00 -0400.
<870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 02 Oct 87 10:41:20 MDT
Message-Id: <9321.560191280@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
After reading through Moon's well thought out and well articulated
proposal for constructors, I have two comments. The first is syntatic,
the second semantic
THE SYNTACTIC
The syntax of the DEFCLASS form is already fairly complex, and adding
an additional option will add yet another construct to this special
sublanguage. If constructors are to be added at all (and see the next
section for arguments why they shouldn't be), then I think a smoother
integration would be to add them as a full fledged form, say
DEFINE-CLASS-CONSTRUCTOR. The advantage of this over having a
class option are that the implementation of the constructor (in the
form of code) is locally close to the declaration of the association
between the constructor name and the class name. In the case
of a class option, the association between a constructor name
and a class name is made in the DEFCLASS form, but the constructor
must actually be defined in a seperate form, as a method or function. From the
point of view of someone reading the code (barring comments, of
course) the fact that a particular method is a constructor is
only apparent if they look back at the DEFCLASS form. I think the advantages
of grouping the definition of the constructor and the declaration
of the association between the constructor name and the class
name outweigh having the class definition and the constructor name
locally close.
THE SEMANTIC
To motivate the following discussion, consider that constructors are
added to the language, and the following code is written using them:
(defclass udc () (a b c) (:constructor udc-cons))
(defun udc-cons (a b c)
(list a b c))
(defmethod doit ((self udc))
(format T "In DOIT for UDC...~S~%" self))
(defmethod doit ((self list))
(format T "In DOIT for LIST...~S~%" self))
(setf obj (udc-cons 1 2 3))
(doit obj)
What happens? Is OBJ a LIST or a UDC? Since it is not possible to
subclass the built-in classes using the default, system supplied
metaclasses, it cannot be both. Either the structure of a UDC
instance is more than a list (meaning that the constructor code,
as written, must be augmented to add some hidden state), or we have
a semantic ambiguity which must be resolved arbitrarily.
The philisophical side of this has to do with how I'd like to
think we want to encourage people to think about the metaclass
protocol. The way I see it (and I may be wrong), among other
things, the metaclass controls the underlying representation of
an instance. Users defining classes should be encouraged to
think about their classes in a more abstract way, and not have
to be concerned about the representation. If they are concerned
about the representation, then an ALLOCATE-INSTANCE method can
be written to control it. It's the job of the compiler writer
to be sure that the default allocation is efficient enough so that
people are encouraged to use it. Considering that the metaclass protocol
is still in the draft stage, it's a bit difficult to argue cases,
but I think the above example could be resolved by writing a new
metaclass which does let you subclass one of the built-in classes.
It may be a lot of work, involving defining new generic function
and method classes as well.
The optimization considerations outlined in the proposal are certainly
of concern, especially for conventional hardware, but, as the example
indicates, adding constructors could lead to having to add code to
method dispatch to resolve ambiguities (or catch them as errors).
Since method dispatch is THE critical item as far as optimization
is concerned, it seems like adding constructors would be a case
of robbing Peter to pay Paul. Of course, as was pointed out in the
proposal, this makes the job of the compiler writer more difficult,
if special cases for MAKE-INSTANCE are to be caught and optimized.
∂02-Oct-87 1017 kempf%hplabsz@hplabs.HP.COM Re: Can defgeneric provide defaults for &key args
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:17:21 PDT
Received: from hplms2 by hplabs.HP.COM with SMTP ; Fri, 2 Oct 87 10:17:21 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 2 Oct 87 09:51:46 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 2 Oct 87 10:52:45 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: Common-Lisp-Object-System@sail.stanford.edu
Subject: Re: Can defgeneric provide defaults for &key args
X-Mailer: mh6.5
In-Reply-To: Your message of 01 Oct 87 10:52:00 -0700.
<871001-105240-3994@Xerox>
Date: Fri, 02 Oct 87 10:52:42 MDT
Message-Id: <9427.560191962@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> I don't think the rules allow a default value to be specified for a
> keyword argument in defgeneric now, even though all methods must accept
> such keys? Should it be allowed to support a uniform default?
Was there some reason why defaults shouldn't be allowed, other than
the case where two different methods would have two different defaults?
Offhand, I can't think of any reason why a uniform default shouldn't
be allowed.
∂02-Oct-87 1032 Moon@STONY-BROOK.SCRC.Symbolics.COM Can defgeneric provide defaults for &key args
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:32:28 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247304; Fri 2-Oct-87 13:33:29 EDT
Date: Fri, 2 Oct 87 13:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Can defgeneric provide defaults for &key args
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871001-105240-3994@Xerox>,
<9427.560191962@hplabsz>
Message-ID: <871002133333.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
We went through this issue at enormous length about a year ago, maybe a
little less than a year. I expect you can find the rationale for the
way generic function argument defaulting is now specified in the mail
archives. If we had maintained a Design Rationale document as we said
we would, it would be in there too.
I, for one, don't feel eager to repeat that lengthy discussion again.
∂02-Oct-87 1054 Gregor.pa@Xerox.COM no-applicable-method
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:54:05 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 10:53:18 PDT
Date: Fri, 2 Oct 87 10:52 PDT
From: Gregor.pa@Xerox.COM
Subject: no-applicable-method
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.stanford.edu
In-Reply-To: <870924-085516-15017@Xerox>
Message-ID: <871002105236.9.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
Date: 24 Sep 87 08:55 PDT
From: Bobrow.pa
(no-applicable-method generic-function first-argument &rest
all-arguments)
This all looks fine except for what I think is a bug in the example.
To use no-applicable-method to build forwarders, we need a class that
is not a subclass of any class except T; hence no methods specialized
on this argument will be applicable to instances of this class. Hence
all calls using an instance of this class as first argument will cause a
trap to no-applicable-method. We write:
(defmethod no-applicable-method (g-f (first forwarder) &rest args)
(send-elsewhere *place* gf first args)))
Actually, I think the following is better:
(defmethod no-applicable-method (g-f (first forwarder) &rest args)
(send-elsewhere *place* gf args))
The point being that this makes it more clear that the &rest argument
really contains all the arguments (the first arg appears in two places).
-------
∂02-Oct-87 1102 Moon@STONY-BROOK.SCRC.Symbolics.COM no-applicable-method
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:02:25 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247364; Fri 2-Oct-87 14:03:15 EDT
Date: Fri, 2 Oct 87 14:03 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: no-applicable-method
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871002105236.9.GREGOR@SPIFF.isl.parc.xerox.com>
Message-ID: <871002140319.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 2 Oct 87 10:52 PDT
From: Gregor.pa@Xerox.COM
Date: 24 Sep 87 08:55 PDT
From: Bobrow.pa
(no-applicable-method generic-function first-argument &rest
all-arguments)
This all looks fine except for what I think is a bug in the example.
I thought we already changed the definition from
(defgeneric no-applicable-method (generic-function first-argument
&rest all-arguments))
to
(defgeneric no-applicable-method (generic-function all-arguments))
Gregor, maybe you're still behind on your mail?
∂02-Oct-87 1132 Bobrow.pa@Xerox.COM Re: Constructors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:32:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 11:32:29 PDT
Date: 2 Oct 87 11:32 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Constructors
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Fri, 02 Oct 87
10:41:20 MDT
To: kempf%hplabsz@hplabs.HP.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM,
Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <871002-113229-5844@Xerox>
Moon argues that constructors are good because they provide:
(1) A cleaner interface for the caller
This is an argument for a functional interface that buries the name. A
defun does that, as Moon points out.
Some reasons to have a :CONSTRUCTOR option in
DEFCLASS are
- to make it easier and more convenient for users to create
constructors
- :CONSTRUCTOR is a convenient abbreviation for something you
could do yourself in a more long-winded way, just like :ACCESSOR
Isn't this another case of making something easier to type, and harder
to read? We are talking about a few extra characters. Are the
following really MUCH more long-winded than the constructor option?
(defun make-foo (&rest initargs) (apply #' make-instance 'foo initargs))
(defun make-foo-2 (&key k1 k2) (make-instance 'foo :k1 k1 :k2 k2))
[Another] reason to have a :CONSTRUCTOR option in
DEFCLASS [is]
- to be culturally consistent with DEFSTRUCT
We certainly have ignored the notion of being "culturally consistent
with DEFSTRUCT" -- to quote Moon "that syntax was designed a long time
ago".
(2) Coordination with class redefinition
Moon argues that creating an option makes constructors lexically local.
But the validity of the constructor is dependent on information that is
inherited from many classes and methods. Hence being included in the
class definition is not as useful as say the :initarg or :accessor
slot-options, which are adjacent to all the information used in their
construction. And :initarg or :accessor slot-options don't effect
anything in subclasses (except for optimizations)
Making this updating automatic is a convenience for
programmers, so they don't have to remember to do it by hand.
I don't undertand which things can be done automagically. If I change
the name of an initarg or method keyword argument, should the text in
which constructors used the old name be changed? Clearly not. What
other changes can be handled that are interesting? What Moon is
suggesting is a general mechanism for notifying the user when the names
of keyword arguments change in a method, so calls can be changed.
(3) More efficient than MAKE-INSTANCE
...
Gregor has argued that calls to MAKE-INSTANCE with a constant
first argument can be equally optimized
...In either case, if we are going to have this type of
mechanism, I would much rather make it explicitly visible as a
:CONSTRUCTOR option than have it operating behind the scenes in
some vaguely defined way.
But I thought the whole point of optimization mechanisms is that they
would operate behind the scenes. I don't quite understand the phrase
"the inherent complexity of making that mechanism generally available"
in this context. I thought this was specific to make-instance, and that
the only other mechanism was a hidden mechanism for generating functions
from a particular type of call, rather than the optimization tricks.
My high order conclusion is that
- constructors are for writers of code, not readers,
- optimizations should be for system implementers,
not something that we force the casual user to be aware of
- programming environments should support finding callers of methods
whose arguments have changed. We might ask what hooks CLOS should
provide for such an environmental feature.
∂02-Oct-87 1154 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Constructors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:53:56 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247454; Fri 2-Oct-87 14:53:25 EDT
Date: Fri, 2 Oct 87 14:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Constructors
To: kempf%hplabsz@hplabs.HP.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <9321.560191280@hplabsz>
Message-ID: <871002145323.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 02 Oct 87 10:41:20 MDT
From: kempf%hplabsz@hplabs.HP.COM
....In the case of a class option, the association between a
constructor name and a class name is made in the DEFCLASS form, but
the constructor must actually be defined in a seperate form, as a
method or function. From the point of view of someone reading the
code (barring comments, of course) the fact that a particular method
is a constructor is only apparent if they look back at the DEFCLASS
form.
Jim, I'm afraid you misunderstood what I was proposing, in an important
way. The :constructor option to defclass completely takes care of
defining the constructor; there is no separate form that "actually
defines" it. Also, constructors are not methods.
Thus in your example
(defclass udc () (a b c) (:constructor udc-cons))
(defun udc-cons (a b c)
(list a b c))
you are defining the function udc-cons twice. First you define it
as a constructor, then you clobber that definition.
Your example is semantically the same as
(defclass udc () (a b c))
(defun udc-cons (&key)
(make-instance 'udc))
(defun udc-cons (a b c)
(list a b c))
As best I can tell, the rest of your comments aren't really applicable,
once this misperception is realized. If after reading this you still
think there are problems with constructors, could you send another
message? I certainly want to be aware of any real semantic problems.
At least one thing is clear from this, which is that if we put in
constructors the explanation in the spec will have to be written more
clearly than the explanation in the draft proposal I mailed out, so
readers cannot misunderstand it in this way. I am not surprised by
this.
∂02-Oct-87 1256 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Constructors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 12:55:46 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247593; Fri 2-Oct-87 15:56:41 EDT
Date: Fri, 2 Oct 87 15:56 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Constructors
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871002-113229-5844@Xerox>
Message-ID: <871002155644.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Evidently my proposal for constructors wasn't very well written, since
so far no one who has read it (and sent mail) has understood it.
Date: 2 Oct 87 11:32 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
(2) Coordination with class redefinition
Moon argues that creating an option makes constructors lexically local.
But the validity of the constructor is dependent on information that is
inherited from many classes and methods. Hence being included in the
class definition is not as useful as say the :initarg or :accessor
slot-options, which are adjacent to all the information used in their
construction. And :initarg or :accessor slot-options don't effect
anything in subclasses (except for optimizations)
I can't understand anything in the above paragraph. I never said
anything about lexical locality, unless you mean "A much simpler way is
to make the constructor syntactically part of the DEFCLASS, so it
naturally gets updated at the same time as the rest of the DEFCLASS.",
which refers to the linkage between the class and the constructor
function necessary for the automatic updating discussed below. The
:initarg and :accessor slot options certainly do affect subclasses.
However, I don't see that's relevant, since the :constructor option does
not affect subclasses. The effect of the :accessor slot option
certainly does depend on sub and superclasses, in any system that
optimizes compilation of SLOT-VALUE, because the position of a slot
is not determined by the single DEFCLASS form. I'm obviously missing
whatever point you were trying to make here.
Making this updating automatic is a convenience for
programmers, so they don't have to remember to do it by hand.
I don't undertand which things can be done automagically. If I change
the name of an initarg or method keyword argument, should the text in
which constructors used the old name be changed? Clearly not. What
other changes can be handled that are interesting? What Moon is
suggesting is a general mechanism for notifying the user when the names
of keyword arguments change in a method, so calls can be changed.
That's certainly not what I'm proposing.
I thought it was clear from the two sentences preceding the one you
quoted what was being updated: "its initargs and their default values."
I should have also mentioned compiler optimizations in this paragraph,
rather than deferring them to later. Although :default-initargs is
enough to make the point, compiler optimizations are in practice the
major part of the updating burden.
Look, it's very simple. If we're going to have a way to optimize out
the interpretive processing that a naive implementation of MAKE-INSTANCE
has to do, and generate specialized compiled code for making instances,
then we have to have some way to redo this optimization when something
changes. I claim it would be terrible for programmers to have to do
that by hand. I claim that constructors are a better way to keep track of
this automatically than any other way, because the special processing is
confined to a system generated function, and kept away from user written
functions. So what are the alternatives? We can decide that we don't
care about speeding up object creation that much, or someone can propose
a specific, coherent alternative.
(3) More efficient than MAKE-INSTANCE
...
Gregor has argued that calls to MAKE-INSTANCE with a constant
first argument can be equally optimized
...In either case, if we are going to have this type of
mechanism, I would much rather make it explicitly visible as a
:CONSTRUCTOR option than have it operating behind the scenes in
some vaguely defined way.
But I thought the whole point of optimization mechanisms is that they
would operate behind the scenes. I don't quite understand the phrase
"the inherent complexity of making that mechanism generally available"
in this context. I thought this was specific to make-instance, and that
the only other mechanism was a hidden mechanism for generating functions
from a particular type of call, rather than the optimization tricks.
I guess neither of us can figure out what the other is talking about here.
Maybe my previous paragraph makes this more clear: I hope so. If not, you
should respond with something very specific, such as an example showing
exactly what a programmer would write to get an efficient constructor.
Perhaps it should be something that has the same semantics as
(defclass class1 ()
((a :initarg :a)
(b :initarg :b)))
(defclass class2 (class1)
((c :initarg :c)
table)
(:default-initargs :b 1)
(:constructor make-2 (a &optional n b c)))
(defmethod initialize-instance :after ((x class2) &key (n 10))
(setf (slot-value x 'table) (make-array n)))
(make-2 "foo" 5)
My high order conclusion is that
- constructors are for writers of code, not readers,
I agree or disagree depending on what you mean. The :constructor option
is primarily an aid to writers of code, although of course it's somewhat
easier to read than the equivalent written out as a defun. Calling a
function to construct something, instead of calling MAKE-INSTANCE
directly, is primarily an aid to readers of code, although it's also
useful to writers, as any form of modularity is.
- optimizations should be for system implementers,
not something that we force the casual user to be aware of
Precisely why I want to package the optimization into a :constructor option
instead of making it visible to the writer of the function to construct something.
- programming environments should support finding callers of methods
whose arguments have changed. We might ask what hooks CLOS should
provide for such an environmental feature.
I assume when you say "methods" you mean "generic functions"; people don't
call methods. I don't think CLOS has to provide any hooks for this, since
I don't think the issue is significantly different for generic functions
than for regular functions. I agree wholeheartedly that programming
environments should provide support for this.
∂02-Oct-87 1342 Bobrow.pa@Xerox.COM Re: Can defgeneric provide defaults for &key args
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 13:42:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 13:43:20 PDT
Date: 2 Oct 87 13:43 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Can defgeneric provide defaults for &key args
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 2 Oct 87 13:33 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <871002-134320-6130@Xerox>
We went through this issue at enormous length about a year ago,
maybe a little less than a year. I expect you can find the
rationale for the way generic function argument defaulting is now
specified in the mail archives. If we had maintained a Design
Rationale document as we said we would, it would be in there too.
I, for one, don't feel eager to repeat that lengthy discussion
again.
I remember the reasons, but at that time did not have the same
congruence rule for keyword arguments. However, I take it from your
response that you feel the same arguments still apply. After some more
thought, I agree with you. There should be no distinction in defaulting
rules between optional and keyword arguments.
∂02-Oct-87 1400 Bobrow.pa@Xerox.COM Re: no-applicable-method
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:00:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 13:50:07 PDT
Date: 2 Oct 87 13:50 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: no-applicable-method
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 2 Oct 87 14:03 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <871002-135007-6157@Xerox>
(no-applicable-method generic-function first-argument &rest
all-arguments)
This all looks fine except for what I think is a bug in the example.
I thought we already changed the definition from
(defgeneric no-applicable-method (generic-function first-argument
&rest all-arguments))
to
(defgeneric no-applicable-method (generic-function all-arguments))
I agree. One must redefine no-applicable-method to call another generic
function that is specialized on the first argument.
(defmethod no-applicable-method (generic-function all-arguments)
(forward-message (car all-arguments) *elsewhere*
(list generic-function all-arguments)))
where the forwarder type understands the method forward-message, and no
other.
Alternatively, no-applicable-method could search the argument list for
an element of the forwarder class to send the message to, else signal an
error. This would not make it so dependent on the first argument.
∂02-Oct-87 1404 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Can defgeneric provide defaults for &key args
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:04:11 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247684; Fri 2-Oct-87 17:05:10 EDT
Date: Fri, 2 Oct 87 17:05 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Can defgeneric provide defaults for &key args
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871002-134320-6130@Xerox>
Message-ID: <871002170519.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 2 Oct 87 13:43 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
There should be no distinction in defaulting
rules between optional and keyword arguments.
I like that way of putting it. A very succinct principle that
is easy to state and easy to understand.
∂02-Oct-87 1404 @RELAY.CS.NET:DUSSUD%Jenner@csl.ti.com Re: Exact type
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:04:31 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah15107; 2 Oct 87 16:23 EDT
Received: from csl.ti.com by RELAY.CS.NET id bn13177; 2 Oct 87 16:20 EDT
Received: from Jenner by tilde id AA20526; Thu, 1 Oct 87 14:33:29 CDT
Message-Id: <2769103900-16110287@Jenner>
Date: Thu, 1 Oct 87 14:31:40 CDT
From: Patrick H Dussud <DUSSUD%Jenner%csl.ti.com@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Exact type
In-Reply-To: Msg of Wed, 30 Sep 87 14:16:36 MST from kempf%hplabsz@hplabs.hp.com
> The user shouldn't expect
> that an argument will be exactly of this built-in type. On some
> machines, you cannot expect an cons cell argument to be always of the
> exact type CONS.
>
Now I think I understand. We're coming from two different directions,
as far as typing is concerned. Your direction seems to be the structural
equivalence one, that is, two data items are of the same exact type
if they have the same structure. My direction is operator equivalence,
two items have the same exact type if you can apply the same set of operators
to them.
For me (this is, if I understand you proposal on optimization correctly)
two types are the same if their applicable methods are the same for all
of their operators. It is a necessary condition for method
discrimination optimization. If you have a built-in type, say CONS and
you write:
(defun foo (x a)
(declare (exact-type cons X))
(rplacd X a)
a)
The compiler would assume that it knows what methods are applicable
to this call to REPLACD and will do some useful optimizations.
However, it may happen that the system supplies foo with a CONS cell of
type STACK-CONS, that you (portable user) didn't expect. The function
foo would not work under this condition because RPLACD has a method
defined on STACK-CONS, shadowing the one on CONS.
I'll rewrite the Cleanup Committee submission to reflect the restriction
you requested (unless I hear other objections), but I'd suggest we change
the name back to EXACT-CLASS, since the built-in types are no longer
covered.
OK.
∂02-Oct-87 1417 Gregor.pa@Xerox.COM no-applicable-method
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:17:34 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 14:15:01 PDT
Date: Fri, 2 Oct 87 14:14 PDT
From: Gregor.pa@Xerox.COM
Subject: no-applicable-method
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871002140319.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <871002141420.0.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
Date: Fri, 2 Oct 87 14:03 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Gregor, maybe you're still behind on your mail?
right
-------
∂02-Oct-87 1640 Gregor.pa@Xerox.COM fixing our problems with setf
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 16:40:11 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 16:38:07 PDT
Date: Fri, 2 Oct 87 16:37 PDT
From: Gregor.pa@Xerox.COM
Subject: fixing our problems with setf
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>, Patrick H
Dussud <DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net>
cc: Common-Lisp-Object-System@Sail.Stanford.edu, Gregor.pa@Xerox.COM
In-Reply-To: <870921163510.2.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<2768308570-8410382@Jenner>,
<870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870921200005.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <871002163721.4.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
As I believe I made clear before, I believe Common Lisp would be a
better language if setf facility it provided was a lot simpler. This
message starts by making more clear what it is I think would have been a
better original design, it then goes on to propose a clean up of setf
which has many of the same nice properties but is compatible with the
current situation.
In my 'improved original design' the setf mechanism would just be an
abbreviation for calling a function whose name was (SETF -symbol-).
There would be no defsetf or any other mechanism for changing the way
the setf macro would expand under certain circumstances. Here is an
example of how this would work:
(setq mex (macroexpand '(setf (foo 1 2) 3)))
(LET ((#:G0 1)
(#:G1 2)
(#:G2 3))
(FUNCALL #'(SETF FOO) #:G2 #:G0 #:G1))
;;;
;;; at this point, assuming there was no previous definition for
;;; (setf foo) attempting to evaluate the form bound to MEX would
;;; signal an error.
;;;
(eval mex)
>Error: undefined function (SETF FOO)...
;;;
;;; but if we define a function (SETF FOO) then eval of mex would work
;;; as expected
(defun (setf foo) (new-value indicator) ...)
What are the features of this mechanism:
The macroexpansion of setf does not depend on any defining form,
lexical environment, compile environment or anything. Because it is not
possible to do a 'top-level' definition for setf expansion, there are no
problems with wanting to do a lexical binding of a rule for setf
expansion.
Also because the expansion of setf does not depend on the argument
list of FOO or (SETF FOO), there can't be any problems with having to
re-expand (recompile) code after the defun for foo or (setf foo)
changes. This rule for setf always puts the new value argument as the
first of the other arguments, this rule always works since it doesn't
depend on the definition of FOO or (SETF FOO).
Of course, proposing to Common Lisp that they completely do away with
defsetf is probably too radical a proposal. But I believe there is a
useful intermediate ground which could help us all.
1) Change the behavior of setf so that in the absence of any
special information provided by defsetf it expands as shown
above.
2) Add the setf function spec to the language to support this.
But note that the forms like defun and defmethod would only
have one lambda-list. The programmer would know that the
function/method will be receiving the new-value as its first
argument.
3) Document very clearly that this is the suggested way of using
setf and that the only real reason to continue using the old
form of setf is to do things like LDB or other fundamentally
macro-ish things.
I believe this proposal solves many of the problems previously raised in
a clean simple way:
Date: Tue, 22 Sep 87 09:36:10 CDT
From: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>
The problem is that we can't always specialize on the new-value argument
using the short defsetf form. The programmer will have to write a hocky
defsetf form to get around the problem of having optional arguments
(e.g. implementing the setf form of SUBSEQ as a generic function). We
lose the COMBINE-LAMBDA-LISTS abstraction.
In this scheme we can always specialize on the new value form since the
programmer can count on it coming in as the first argument to the setf
function.
Date: Mon, 28 Sep 87 16:55 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
The next issue is what to do about the lambda-list of a setf-function.
We already agreed on what is the lambda-list in the expansion of
(defun (setf foo) ...) into
(setf (symbol-function '(setf foo)) #'(lambda ...)). Specifically,
#'(setf foo) takes one more required argument than #'foo, and the last
required argument is the new value to be stored.
The issue is whether certain function-defining macros should have a
special syntax with two lambda-lists when defining a setf function, or
should use their normal syntax. The macros in question are defun, flet,
labels, defgeneric, defmethod, and the :method option to defgeneric,
generic-flet, generic-labels, and with-added-methods. In favor of two
lambda-lists is that it's easier for the programmer to see which
parameter is bound to the new value to be stored. In favor of one
lambda-list is syntactic consistency between setf functions and regular
functions. At the meeting two weeks ago, we favored two lambda-lists,
but I now believe that that was a mistake. The rule that the new value
is the last required argument should not be at all difficult for
programmers to understand. Syntactic consistency is important.
I believe making it be the first argument is better because the rule you
propose loses in the following scenario.
(defun foo (a b) ..)
(defun (setf foo) (a b new-value) ..)
(defun code-calling-setf-of-foo ()
(setf (foo a b) c))
Now at this point the programmer realizes that they would rather have
the second argument to FOO be optional. But they are screwed because
they have to go back and recompile all the code that uses setf of foo.
The remaining issue is a scoping issue. We have introduced lexically
local setf functions, where before Common Lisp only had lexically global
setf macros. Thus the namespace of setf operators has been extended to
have a lexical component, just like the namespace of regular operators.
(Recall that "operator" means the union of functions, macros, and
special forms). Regular functions and setf functions naturally come in
pairs, but since they are defined separately we have to specify what
happens in various cases where only one is defined at a given lexical
contour.
Scoping is not a problem in my proposal provided the programmer never
uses defsetf. Because setf always expands the same way, all the
programmer needs to do is provide lexical definitions for the actual
setf function (SETF FOO).
-------
∂03-Oct-87 1149 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/local;class/instance
Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 3 Oct 87 11:49:18 PDT
Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP
id AA10829; Sat, 3 Oct 87 14:49:43 EDT
Received: by mcvax.cwi.nl; Sat, 3 Oct 87 04:11:25 +0100 (MET)
Received: by inria.inria.fr; Fri, 2 Oct 87 19:22:53 +0100 (MET)
Date: Fri, 2 Oct 87 19:22:53 +0100
From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe)
Message-Id: <8710021822.AA13243@inria.inria.fr>
To: Bobrow.pa@xerox.com, inria!inria.inria.fr!cointe@uunet.UU.NET
Subject: Re: Shared/local;class/instance
Cc: RPG@sail.stanford.edu, common-lisp-object-system@sail.stanford.edu
Yes i would prefer shared/insatance...
(if fact that is exactly our proposal (briot and me) descriebed in
our last Ijcai paper).
Pierre
∂03-Oct-87 1300 Gregor.pa@Xerox.COM Constructors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Oct 87 13:00:20 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 03 OCT 87 12:59:53 PDT
Date: Sat, 3 Oct 87 12:59 PDT
From: Gregor.pa@Xerox.COM
Subject: Constructors
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>, Danny Bobrow
<Bobrow.pa@Xerox.COM>
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU,
kempf%hplabsz@hplabs.HP.COM
In-Reply-To: <870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<871002-113229-5844@Xerox>,
<871002145323.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <871003125948.1.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
This message contains my comments about constructors. I wrote this
quickly, but I have been thinking about it for a while. This means that
this may sound a little rough or confused, but I believe pretty firmly
what I am trying to say. If there is a part that seems confusing give
it another read. I won't be reading any more mail until after OOPSLA,
so I won't be able to respond to responses to this till then.
Date: Wed, 30 Sep 87 12:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
This is a proposal to add constructors back into CLOS, now that the basic
object creation protocol has been agreed upon.
WHY HAVE CONSTRUCTORS?
(1) A cleaner interface for the caller
It's often appropriate to have a more abstract interface than the one provided
by MAKE-INSTANCE. Providing a constructor as the documented inter-module
interface for making a particular kind of object encourages users of the
interface to think in more abstract, conceptual terms. Using a constructor
also allows more aspects of the implementation to be changed without changing
the interface: the class name and initarg names could be changed, or the data
representation could be changed to a DEFSTRUCT representation or a
standard-type, without changing the interface. The constructor could even be
replaced by an interface function that does some complex computations to
decide what type of object to create, or to decide whether to return an
existing object or create a new one.
It is true that sometimes, constructors present a more appropriate
interface for the caller. On the other hand, it is often the case that
they are not a more appropriate interface for the caller since if the
caller decides to make a intance of a slightly more specialized version
of something they must either define a new constructor or resort to
calling make-instance.
Also, I believe that much of the functionality you say can be gotten
with constructors can be gotten just as well with make-instance. By
using individual methods on make-instance, it would be easy for a
programmer to have code that for a particular class "does some complex
computations to decide what type of object to create, or to decide
whether to return an existing object or create a new one". Some might
argue that individual methods on make-instance are bad style, (I don't
know what I think) but I believe that argument would be an equally
strong argument against that kind of constructor function.
Also, if we decide to do structure-class (I assume we will) the
programmer could change to a defstruct and still use code that calls
make-instance.
Also, while it is true that these are reasonable arguments for the use
of constructors as an interface to the caller, they are not arguments
for why there should be a :constructor option. I understand that you go
on to acknowledge that, but I wanted to make it clear.
These needs could be met simply by defining constructor functions
with DEFUN and advertising them. Some reasons to have a
:CONSTRUCTOR option in DEFCLASS are
- to make it easier and more convenient for users to create
constructors
As Danny says, I believe this sacrifices reading ease in favor of
typing ease in a serious way.
- to be culturally consistent with DEFSTRUCT
I agree with Danny about this too.
- :CONSTRUCTOR is a convenient abbreviation for something you could
do yourself in a more long-winded way, just like :ACCESSOR
Sort of, but :accessor is a more trivial case. But perhaps we should get
rid of :accessor? (Later in this message I make more comments about
:accessor.)
Other reasons appear below.
(2) Coordination with class redefinition
As the bridge between an external interface and the internal structure
of a class, a constructor function contains certain information about
the class, such as what are its initargs and their default values. When
a class is redefined, any constructors for the class and its subclasses
should be updated if necessary to keep them consistent with the class.
Making this updating automatic is a convenience for programmers, so they
don't have to remember to do it by hand. One way to make the updating
automatic would be to add a new feature to the programming environment
by which a linkage could be established between a function and a class
so that redefining the class makes some edits to the source of the
function and then recompiles it. A much simpler way is to make the
constructor syntactically part of the DEFCLASS, so it naturally gets
updated at the same time as the rest of the DEFCLASS. This is another
way in which constructors are analogous to accessors.
I believe this is the strongest argument I have heard for constructors.
But lets look at it for a minute.
- Lets suppose that someone is defining boa constructors by hand (using
defun). Presumably their reason for doing this is that they want to
present a boa interface to a subset of the total initargs the function
accepts. In that case, changes to the class lattice which affect the
initargs the embedded call to make-instance accepts can have one of two
effects:
1: They don't change the initargs the constructor is presenting
a boa interface to. In this case the original constructor
defun is more than likely still semantically and syntactically
correct.
2: They do affect the initargs the constructor is presenting a boa
interface to. In this case the constructor defun is going to have
to be examined and perhaps edited. But in this case what would
having a :constructor option to defclass have bought the user?
Nothing as near as I can tell, they will still have to examine
that :constructor option and perhaps edit it.
The point being that in general, if there is a change which affects the
initargs a constructor is providing a boa interface to the programmer is
going to have to examine the constructor to make sure it is still valid.
Now lets look at the case where the constructor is not providing a boa
interface but rather is providing just a initarg interface like make
instance. In this case the constructor looks like:
(defun make-foo (&rest args)
(apply #'make-instance 'foo args))
Well in this case the code defined with defun will always be valid under
changes to the class lattice, only the code that actually calls make-foo
can become incorrect and so once again I see no real benefit being
provided by the :constructor option.
(3) More efficient than MAKE-INSTANCE
Gregor has argued that calls to MAKE-INSTANCE with a constant first
argument can be equally optimized, since the exact class being
constructed is known. While this is true in theory, it seems that
either a complicated mechanism would be needed to make sure that the
function was recompiled when the class was redefined in a way that
invalidated the inline code, or else there would have to be user-visible
declarations to control the tradeoff between performance and robustness
in the face of class redefinition. Alternatively, calls to
MAKE-INSTANCE with a constant first argument could be turned into calls
to a constructor function that was created behind the scenes. Then if
the class was redefined, only the constructor function would have to be
recompiled. In either case, if we are going to have this type of
mechanism, I would much rather make it explicitly visible as a
:CONSTRUCTOR option than have it operating behind the scenes in some
vaguely defined way.
What you describe as the alternative is the only way I have thought of
doing it and I don't in any way see why this is harder to implement that
the mechanism you are proposing. I do believe I have show the two be be
of equivalent difficulty to implement.
Also, I don't really believe semantic preserving optimizations need to
be made explicit. That is the opposite of what a (safe) compiler
optimization means to me.
Whats more, if we explicitly document that :constructors are likely to
be faster than make-instance we will be encouraging users to use
constructors all the time rather than make-instance and I think that
would be bad bad bad.
WHY GET RID OF CONSTRUCTORS?
(1) Simplicity
If we have both constructors and MAKE-INSTANCE, then we have two ways to
do the same thing.
[But CLOS very often provides both a primitive mechanism and a convenient
abbreviation for a common case of using that mechanism.]
The rules for mapping constructor parameter names into slots and initargs are
complicated and confusing.
[Very true. In this proposal they have been enormously
simplified.]
I must confess that the rules you propose here are simpler than those
before.
(2) Avoid hiding mechanisms
Constructors contain a hidden performance optimization, in that there is
more inlining in their bodies than can be achieved through documented
mechanisms elsewhere.
[I argued above that this is preferable to the inherent complexity of
making that mechanism generally available. Of course there is nothing
to stop us from documenting it if that's what we really want.
Also, exactly the same thing could be said about :ACCESSOR, at least
in the Symbolics implementation.]
See my comment above about how bad it would be to explicitly say that
constructors are faster than make-instance.
Also note that it would be trivial to teach your implementation (and
mine) to reckognize the following and optimize it the same way as
accessors:
(defmethod foo-x ((foo foo)) (slot-value foo 'x))
(3) Not more efficient than MAKE-INSTANCE
(see discussion above)
I have read carefully the rest of the message which contains the details
of the proposal, but am not going to comment on those details here other
than to say that as a proposal for constructors they seem reasonable.
Summary:
I am still opposed to adding constructors to CLOS. I do believe that
they will make life a little more convenient for some programmers, but I
don't think those advantages outweigh the conceptual problems I outline
above nor do I think they are worth the added complexity of having to
describe and understand how they work and documenting the mechanism
which is used to compile them and cause them to get recompiled when
appropriate.
-------
∂03-Oct-87 1341 Gregor.pa@Xerox.COM Re: Constructors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Oct 87 13:41:46 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 03 OCT 87 13:26:17 PDT
Date: Sat, 3 Oct 87 13:26 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Constructors
To: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <871002155644.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <871003132624.4.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
Date: Fri, 2 Oct 87 15:56 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Look, it's very simple. If we're going to have a way to optimize out
the interpretive processing that a naive implementation of MAKE-INSTANCE
has to do, and generate specialized compiled code for making instances,
then we have to have some way to redo this optimization when something
changes. I claim it would be terrible for programmers to have to do
that by hand. I claim that constructors are a better way to keep track of
this automatically than any other way, because the special processing is
confined to a system generated function, and kept away from user written
functions. So what are the alternatives? We can decide that we don't
care about speeding up object creation that much, or someone can propose
a specific, coherent alternative.
I guess neither of us can figure out what the other is talking about here.
Maybe my previous paragraph makes this more clear: I hope so. If not, you
should respond with something very specific, such as an example showing
exactly what a programmer would write to get an efficient constructor.
Perhaps it should be something that has the same semantics as
(defclass class1 ()
((a :initarg :a)
(b :initarg :b)))
(defclass class2 (class1)
((c :initarg :c)
table)
(:default-initargs :b 1)
(:constructor make-2 (a &optional n b c)))
(defmethod initialize-instance :after ((x class2) &key (n 10))
(setf (slot-value x 'table) (make-array n)))
(make-2 "foo" 5)
I don't understand why make-2 has to be any faster at all than:
(defun make-3 (a &optional n b c)
(make-instance 'class2 :a a :n n :b b :c c))
And I still don't understand what other convenience is gotten from this
in the way of automatically fixing stuff if one of the defclasses
changes.
-------
∂03-Oct-87 1451 mcvax!inria.inria.fr!cointe@uunet.UU.NET Re: Shared/local;class/instance
Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 3 Oct 87 14:51:05 PDT
Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP
id AA13067; Sat, 3 Oct 87 17:51:29 EDT
Received: by mcvax.cwi.nl; Sat, 3 Oct 87 04:19:34 +0100 (MET)
Received: by inria.inria.fr; Fri, 2 Oct 87 19:29:15 +0100 (MET)
Date: Fri, 2 Oct 87 19:29:15 +0100
From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe)
Message-Id: <8710021829.AA13397@inria.inria.fr>
To: Bobrow.pa@xerox.com, inria!inria.inria.fr!cointe@uunet.UU.NET
Subject: Re: Shared/local;class/instance
Cc: RPG@sail.stanford.edu, common-lisp-object-system@sail.stanford.edu
Yes, i would prefer the couple shared/instance.
Here is a copy of our Ijcai paper conclusion:
"We propose to keep the term class variable BUT to use it for
a different meaning> . A class variable becomes an instance variable of
the class treated as an object. To rename the Smalltalk term class variable
we suggest the term "sharedClass" variable."
Pierre